0%

Javascript is a single threaded language. This means it has one call stack and one memory heap. As expected, it executes code in order and must finish executing a piece code before moving onto the next. It’s synchronous, but at times that can be harmful. For example, if a function takes awhile to execute or has to wait on something, it freezes everything up in the meanwhile.

A good example of this happening is the window alert function. alert("Hello World")

You can’t interact with the webpage at all until you hit OK and dismiss the alert. You’re stuck.

So how do we get asynchronous code with Javascript then?

Well, we can thank the Javascript engine (V8, Spidermonkey, JavaScriptCore, etc…) for that, which has Web API that handle these tasks in the background. The call stack recognizes functions of the Web API and hands them off to be handled by the browser. Once those tasks are finished by the browser, they return and are pushed onto the stack as a callback.

Open your console and type window then press enter. You’ll see most everything the Web API has to offer. This includes things like ajax calls, event listeners, the fetch API, and setTimeout. Javascript uses low level programming languages like C++ to perform these behind the scenes.

Let’s look at a simple example, run this code your console:

1
2
3
4
5
console.log("first")
setTimeout(() => {
console.log("second")
}, 1000)
console.log("third")

What did we get back?

1
2
3
4
first
third
undefined
second

Feels odd, right? Well, let’s break this down line by line:

console.log("first") is on the stack first, so it gets printed. Next, the engine notices setTimeout, which isn’t handled by Javascript and pushes it off to the WebAPI to be done asynchronously. The call stack moves on without caring about the code handed off to the Web APIs and console.log("three") is printed.

Next, the Javascript engine’s event loop kicks in, like a little kid asking “Are we there yet?” on a road trip. It starts firing, waiting for events to be pushed into it. Since the setTimeout isn’t finished, it returns undefined, as the default, well because it hasn’t been given the value yet. Once the callback finally does hits we get console.log("second") printed.

There’s a really good site that slows this all down and shows this happening.

http://latentflip.com/loupe

I suggest playing around in this sandbox to help solidify your understanding. It helped me get a feel for how asynchronous code can work with Javascript being single threaded.

Ref:https://dev.to/bbarbour/if-javascript-is-single-threaded-how-is-it-asynchronous-56gd

https://stackoverflow.com/questions/51007636/how-javascript-single-threaded-and-asynchronous

JavaScript has a concurrency model based on an event loop, which is responsible for executing the code, collecting and processing events, and executing queued sub-tasks.This model is quite different from models in other languages like C and Java.

Run Time Concepts

Stack, heap, queue

Stack

Function calls form a stack of frames.

1
2
3
4
5
6
7
8
9
10
11
function foo(b) {
let a = 10
return a + b + 11
}

function bar(x) {
let y = 3
return foo(x * y)
}

const baz = bar(7) // assigns 42 to baz

Copy to Clipboard

Order of operations:

  1. When calling bar, a first frame is created containing references to bar‘s arguments and local variables.
  2. When bar calls foo, a second frame is created and pushed on top of the first one, containing references to foo‘s arguments and local variables.
  3. When foo returns, the top frame element is popped out of the stack (leaving only bar‘s call frame).
  4. When bar returns, the stack is empty.

Note that the arguments and local variables may continue to exist, as they are stored outside the stack — so they can be accessed by any nested functions long after their outer function has returned

Heap

Objects are allocated in a heap which is just a name to denote a large (mostly unstructured) region of memory.

Queue

A JavaScript runtime uses a message queue, which is a list of messages to be processed. Each message has an associated function that gets called to handle the message.

At some point during the event loop, the runtime starts handling the messages on the queue, starting with the oldest one. To do so, the message is removed from the queue and its corresponding function is called with the message as an input parameter. As always, calling a function creates a new stack frame for that function’s use.

The processing of functions continues until the stack is once again empty. Then, the event loop will process the next message in the queue (if there is one),so some of event loop’s task is clear queue & stack.

Event loop

The event loop got its name because of how it’s usually implemented, which usually resembles:

1
2
3
while (queue.waitForMessage()) {
queue.processNextMessage()
}

Copy to Clipboard

queue.waitForMessage() waits synchronously for a message to arrive (if one is not already available and waiting to be handled).

“Run-to-completion”

Each message is processed completely before any other message is processed.

This offers some nice properties when reasoning about your program, including the fact that whenever a function runs, it cannot be pre-empted and will run entirely before any other code runs (and can modify data the function manipulates). This differs from C, for instance, where if a function runs in a thread, it may be stopped at any point by the runtime system to run some other code in another thread.

A downside of this model is that if a message takes too long to complete, the web application is unable to process user interactions like click or scroll. The browser mitigates this with the “a script is taking too long to run” dialog. A good practice to follow is to make message processing short and if possible cut down one message into several messages.

Adding messages

In web browsers, messages are added anytime an event occurs and there is an event listener attached to it. If there is no listener, the event is lost. So a click on an element with a click event handler will add a message—likewise with any other event.

Several runtimes communicating together

A web worker or a cross-origin iframe has its own stack, heap, and message queue. Two distinct runtimes can only communicate through sending messages via the postMessage method. This method adds a message to the other runtime if the latter listens to message events.

Never blocking

A very interesting property of the event loop model is that JavaScript, unlike a lot of other languages, never blocks. Handling I/O is typically performed via events and callbacks, so when the application is waiting for an IndexedDB query to return or an XHR request to return, it can still process other things like user input.

Ref:https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

Introduction to Vue.js

What is Vue Router

Learn vuex in 15 minutes

Reactivity in Depth

image

Tips:

  • In a traditional app that is not using client-side routing,the browser is essentially going out and fetching the different content that we need from those different urls
  • With a Single Page Application,we’re really only looking at one page,the index.html,and as we click around in it, we’re adjusting which view we’re seeing of that app, hence we call it a single page application, because all of these pages come from that one index.html page.
  • 【router-view】 is a placeholder replaced by route’s component
  • In client-side routing,when navigation happens, Vue with the help of Vue router compares and renders the differences without ever having to reload the page

image

image

image

image

Q:What is One-Way Data Flow

A: All props form a one-way-down binding between the child property and the parent one:when the parent property updates,it will flow down to the child,but not the other way around.This prevents child components from accidentally mutating the parent’s state, which can make your app’s data flow harder to understand.

Ref:https://vuejs.org/v2/guide/components-props.html#One-Way-Data-Flow

Q:What is Computed Property

A: In-template expressions are very convenient, but they are meant for simple operations. Putting too much logic in your templates can make them bloated and hard to maintain. For example:

1
2
3
<div id="example">
{{ message.split('').reverse().join('') }}
</div>

At this point, the template is no longer simple and declarative. You have to look at it for a second before realizing that it displays message in reverse. The problem is made worse when you want to include the reversed message in your template more than once.That’s why for any complex logic, you should use a computed property.Computed property is much more like a function,but what’s the difference? For the end result, the two approaches are indeed exactly the same. However, the difference is that computed properties are cached based on their reactive dependencies. A computed property will only re-evaluate when some of its reactive dependencies have changed. This means as long as message has not changed, multiple access to the reversedMessage computed property will immediately return the previously computed result without having to run the function again.In comparison, a method invocation will always run the function whenever a re-render happens.

Ref:https://vuejs.org/v2/guide/computed.html#Computed-vs-Watched-Property

The Route Object

A route object represents the state of the current active route. It contains parsed information of the current URL and the route records matched by the URL.The route object is immutable.Every successful navigation will result in a fresh route object

image

cat

  • short for “concatenate”

  • allows us to create single or multiple files,view content of a file, concatenate files and redirect output in terminal or files

    image

电脑默认安装java 16,需要更换为java 8

1
open /Library/Java/JavaVirtualMachines/

选择想要删除的版本,输入管理员密码

点击下载java8dmg安装

1
2
3
4
java -version
openjdk version "1.8.0_312"
OpenJDK Runtime Environment (Zulu 8.58.0.13-CA-macos-aarch64) (build 1.8.0_312-b07)
OpenJDK 64-Bit Server VM (Zulu 8.58.0.13-CA-macos-aarch64) (build 25.312-b07, mixed mode)

完。

参考:https://www.anotheriosdevblog.com/installing-homebrew-and-jenkins-on-my-m1-mac-mini/

今日安装jenkins,出现报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
arch -arm64 brew install jenkins
==> Downloading https://mirrors.ustc.edu.cn/homebrew-bottles/bottles/openjdk%4011-11.0.10.arm64_big_sur.bottle.1.tar.gz
#=#=#
curl: (22) The requested URL returned error: 404
Warning: Bottle missing, falling back to the default domain...
==> Downloading https://ghcr.io/v2/homebrew/core/openjdk/11/manifests/11.0.10-1
Already downloaded: /Users/kevin/Library/Caches/Homebrew/downloads/c92dbb3dbfa86fe1cdbe7a74ec208c3789d188d92be2d580af208aef5b80a197--openjdk@11-11.0.10-1.bottle_manifest.json
==> Downloading https://ghcr.io/v2/homebrew/core/openjdk/11/blobs/sha256:8990371b4279802b949bcff3a2064ea0a51e7a64da7449267a1c4021e2d7d6d8
Already downloaded: /Users/kevin/Library/Caches/Homebrew/downloads/92754dc32a66d4a7c38ea48c4e3820236bf633e1bd5949f96cd13a502a14f41f--openjdk@11--11.0.10.arm64_big_sur.bottle.1.tar.gz
==> Downloading https://mirrors.ustc.edu.cn/homebrew-bottles/bottles/jenkins-2.302.all.bottle.tar.gz
#=#=#
curl: (22) The requested URL returned error: 404
Warning: Bottle missing, falling back to the default domain...
==> Downloading https://ghcr.io/v2/homebrew/core/jenkins/manifests/2.302
Already downloaded: /Users/kevin/Library/Caches/Homebrew/downloads/a7cf18dfe095a4d331d7905c74417d764e90ace995b98a023bfae85aced3cb0f--jenkins-2.302.bottle_manifest.json
==> Downloading https://ghcr.io/v2/homebrew/core/jenkins/blobs/sha256:fc7f49175e23a67127dc70338bd12abac822048f12b213fc666e1f9499ff6e82
Already downloaded: /Users/kevin/Library/Caches/Homebrew/downloads/eb6411ff42c44cb186e34607b5ac9d17d67777a07a985ad36570e9001354fae7--jenkins--2.302.all.bottle.tar.gz
==> Installing dependencies for jenkins: openjdk@11
==> Installing jenkins dependency: openjdk@11
==> Pouring openjdk@11-11.0.10.arm64_big_sur.bottle.1.tar.gz
tar: Error opening archive: Failed to open '/Users/kevin/Library/Caches/Homebrew/downloads/1096bb647c4eefa040e362e9f88af881902e3cfd88dc4bb9daab7319cda7ab44--openjdk@11-11.0.10.arm64_big_sur.bottle.1.tar.gz'
Error: Failure while executing; `tar --extract --no-same-owner --file /Users/kevin/Library/Caches/Homebrew/downloads/1096bb647c4eefa040e362e9f88af881902e3cfd88dc4bb9daab7319cda7ab44--openjdk@11-11.0.10.arm64_big_sur.bottle.1.tar.gz --directory /private/tmp/d20211129-8757-13q6qjl` exited with 1. Here's the output:
tar: Error opening archive: Failed to open '/Users/kevin/Library/Caches/Homebrew/downloads/1096bb647c4eefa040e362e9f88af881902e3cfd88dc4bb9daab7319cda7ab44--openjdk@11-11.0.10.arm64_big_sur.bottle.1.tar.gz'

解决方案

1
2
export HOMEBREW_BOTTLE_DOMAIN=''
arch -arm64 brew install jenkins

分析:

1
2
3
open ~/.zprofile
export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.ustc.edu.cn/homebrew-bottles/bottles #ckbrew
eval $(/opt/homebrew/bin/brew shellenv) #ckbrew

可以看到是中科大的镜像,未和官网完成同步,五月一号起官网已不再支持bintray服务,把域名切换为空即可

完。

参考:https://www.tinkol.com/372

需求描述:

打一次包,用户可以自由切换开发和生产环境

实现原理

每一个app在设置界面可以增加配置选项,存的数据可以通过user default读取,根据存储的数据来甄别切换网络

实现步骤

  • 新增setting bundle image

root.plist source code 如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>StringsTable</key>
<string>Root</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSMultiValueSpecifier</string>
<key>Title</key>
<string>环境</string>
<key>Key</key>
<string>env_key</string>
<key>DefaultValue</key>
<string>1</string>
<key>Titles</key>
<array>
<string>DEV</string>
<string>TEST</string>
<string>PROD</string>
<string>SAAS</string>
</array>
<key>Values</key>
<array>
<string>1</string>
<string>2</string>
<string>3</string>
<string>4</string>
</array>
</dict>
</array>
</dict>
</plist>

效果:image

image

  • 代码获取值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    - (void)registerDefaultsFromSettingsBundle{
    NSString *settingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];

    if(!settingsBundle) {
    NSLog(@"Could not find Settings.bundle");
    return;
    }

    NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent:@"Root.plist"]];

    NSArray *preferences = [settings objectForKey:@"PreferenceSpecifiers"];

    NSMutableDictionary *defaultsToRegister = [[NSMutableDictionary alloc] initWithCapacity:[preferences count]];

    for(NSDictionary *prefSpecification in preferences) {
    NSString *key = [prefSpecification objectForKey:@"Key"];

    if(key) {
    [defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key];
    }

    }

    [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister];
    }


    -(NSString *)getNetworkOption{
    #if DEBUG
    id obj = [[NSUserDefaults standardUserDefaults] objectForKey:@"env_key"];
    if ([obj isKindOfClass:[NSString class]]) {
    return (NSString *)obj;
    }
    return @"";

    #else
    return @"";

    #endif

    }
  • 设置release状态不包含bundle文件

    Xcode—->Project—->Build Settings—->Build Options—->Exclude Source Files Names—->Release 把文件拖进去

完。

参考:https://blog.csdn.net/nogodoss/article/details/21938771

查单词

遇见一个新的单词,分三步:

  • 去查单词的英文解释,去猜大概的意思

网址:https://www.ldoceonline.com/

tip:看单词意思时可以看看单词的来源origin,拉丁?法语?西语?可以帮助理解单词

  • 打开谷歌,查询单词对应的图片

网址:https://www.google.com/imghp?hl=en

  • 看着图片,听十次单词的发音,让大脑把声音和图像建立连接

听广播

福克斯live:https://radio.foxnews.com/player-files/radio.php

WNYC: https://www.wnyc.org/?gclid=CjwKCAiA4veMBhAMEiwAU4XRrwNPDuvJZfNt-j899F9FDUh3SiWtsg99NlUml5nMb4Z8eVDpuyJG-BoC_OwQAvD_BwE

tip:在家或者坐公交带着耳机听,听懂多少算多少,别慌,手机去商店下载国外广播app

看影视剧

油管:https://www.youtube.com/

学习图形化数学:https://www.3blue1brown.com/

Curious George 动画系列

tip:一定要注意,看无字幕

看八卦新闻

reddit:https://www.reddit.com/

电子书

PDF电子书:https://www.pdfdrive.com/

tip:寻找感兴趣的领域书籍阅读

纸质书推荐

Nights in Rodanthe》by Nicholas Sparks (2002)

Nothing Lasts Forever》by Roderick Thorp (1979)

《The Old Man and the Sea》by Ernest Hemingway (1952)

《The Call of the Wild]》by Jack London (1903)

词典

英英词典:https://www.zhihu.com/question/21964466

tip:一定要使用英英词典,个人使用的是mac自带的词典+朗文第五版的词库

语言获取原理

Second Language Acquisition

《找对英语学习方法的第一本书》

《把你的英语用起来!》

《人人都能用英语》

英语学习的一些经验

解谜英语语法

为什么需要熟练英语

如何超过大多数人

用惯了Android Studio底部直接可以用terminal,在想Xcode是不是可以有类似功能,经过查询,整理出方法

  • 新建一个.sh文件,内容如下,保存
1
2
3
#!/bin/bash

open -a Terminal "`pwd`"
  • 打开Xcode—>Preference—>Behaviors—>Custom—>Run,选择创建好的.sh文件,Run前面的checkbox打钩,设定一个快捷键,这样,在Xcode界面使用快捷键就可以打开当前文件夹的终端窗口了。

完。

参考:https://stackoverflow.com/questions/21998706/terminal-window-inside-xcode

QR code,Quick Response,一种矩阵条形码,二维条形码,在1994年由供职于日本电装公司Denso Wave(丰田子公司)一名职员腾弘原(Masahiro Hara)发明,灵感来源于围棋,用于追踪流水线上的汽车,二维码之所以能快速在汽车制造领域外流行是因为自身的快速读取性,高存储性,更低的容错率,不需要特殊的设备读取。

image

image

image

二维码里可包含地理信息,身份标识,网页地址,是对这些信息进行了编码

可编码的原始信息可分为四种:

编码模式 内容
Numeric 1234567890
Alphanumeric ABCDE…..Z 1234567890
Byte 0000111100001111
Kanji 漢字の部首・画数・読み方・筆順・意味などを調べることができる漢字辞典サイトで

每一种模式使用不同的方法把text转换为比特,尽可能使用效率高的方法,编码后的结果是一串比特,8bit为一个单位,称为data codeword。

二维码拆分

image

image

1 .Quiet zone: 二维码存放的区域,白色底板,用来和其他的图案隔离开来,比如被玷污的信封上,报纸上或者有过摩擦的纸箱表面

2.Finder patterns:左上,右上,左下的三个黑白正方形,用来确认是否为二维码,以及二维码的旋转方向

3.Alignment pattern: 在非正常情况下用来确保可以正常解码,比如印在凸面上,扫描角度不正等

4.Timing pattern:紫色连线部分,小黑白方块组成,用来辅助确认二维码里具体的信息(data cell),尤其是二维码污损的情况下

5.Version infomation:绿色部分,用来确认版本信息

6.Data Cells:剩余的黑白点部分,全为具体数据

容错率

Error Correction Level Error Correction Capability
L (low) Recovers 7% of data
M (medium) Recovers 15% of data
Q (quarter) Recovers 25% of data
H (high) Recovers 30% of data

容错率的特点是在原始数据后面加上Reed-Solomon Code。打个比方,一段原始数据里包括100个codeword,需要修复50个,那么需要在数据尾部挂上100个Reed-Solomon code(两倍),这样下来总数为200codeword,容错率为25%,容错等级为Q。也可以认为刚才的例子容错率为50%,鉴于在通常情况下数据部分会污损,所以还是按25%来。容错率越高,数据越大

PS:Reed-Solomon Code 是一种在制作音乐CD领域较为常用的数学方法,一开始发明用来卫星或者星际通讯降噪,可以在比特级纠错

确定数据使用的最小版本

最小的二维码为21 * 21像素,最大是177 * 177像素,不同的尺寸代表不同版本,21 * 21为version 1,25 * 25为version 2,4个像素为一个步进,以此类推,177 * 177为version 40。

每一个版本都有数据容量上限,数据容量取决于编码的信息长度和纠错级别,字符容量表展示了每个版本不同纠错级别的容量

打个比方,HELLO WORLD包含11个字符,使用Q级别纠错,版本1 Alphanumeric最大容量是16字符,那么版本一就是HELLO WORLD最低版本,依次类推

下表是二维码数据容量的上限

Encoding Mode Maximum number of characters a 40-L code can contain in that mode
Numeric 7089 characters
Alphanumeric 4296 characters
Byte 2953 characters
Kanji 1817 characters

添加模式标识

每一种编码模式机器需要通过在数据前添加标识来确定,HELLO WORLD的编码代码为表格第二行,0010

Mode Name Mode Indicator
Numeric Mode 0001
Alphanumeric Mode 0010
Byte Mode 0100
Kanji Mode 1000
ECI Mode 0111

添加个数标识

个数标识表示字符串长度,HELLO WORLD长度为11,二进制1011,版本1的比特位长度为9,在左边补齐0,结果为 00000 1011,添加在模式标识后为 0010,00000 1011

下面是各版本规定的比特位长度

Versions 1 - 9

Mode Bits
Numeric 10
Alphanumeric 9
Byte 8
Japanese 8

Versions 10 - 26

Mode Bits
Numeric 12
Alphanumeric 11
Byte 16
Japanese 10

Versions 27 - 40

Mode Bits
Numeric 14
Alphanumeric 13
Byte 16
Japanese 12

真实数据编码

HELLO WORLD Alphanumeric模式为例,参考编码表为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
A 10
B 11
C 12
D 13
E 14
F 15
G 16
H 17
I 18
J 19
K 20
L 21
M 22
N 23
O 24
P 25
Q 26
R 27
S 28
T 29
U 30
V 31
W 32
X 33
Y 34
Z 35
36 (space)
$ 37
% 38
* 39
+ 40
- 41
. 42
/ 43
: 44

把字符串拆分为如下形式,O和空格在一起

1
HE,LL,O ,WO,RL,D

找到对应的数字

H → 17
E → 14

第一个乘以45,加第二个

(45 * 17) + 14 = 779

转换为11bit长的字符串,左边补0

779 → 01100001011

以此类推得到所有的数据,最后一位D -> 13 转换长度为6比特 001101

Mode Indicator Character Count Indicator Encoded Data
0010 000001011 01100001011 01111000110 10001011100 10110111000 10011010100 001101

转换为8-bit CodeWord

二维码要求数据必须填满,参考纠错表,此处,我们采用的是版本一,Q级别,可以有13个CW,每个CW为8-bit,总容量为13*8=104bit,到了这一步,我们的数据总长度为74,离满格还差34,需要在尾部添加四个0,最多四个,如果数据长度为102,则补齐两个0,以此类推,到现在我们的数据为

Mode Indicator Character Count Indicator Encoded Data Terminator
0010 000001011 01100001011 01111000110 10001011100 10110111000 10011010100 001101 0000

拆分补齐数据,使之长度为8的倍数

74 + 4 = 78bit,在末尾添加00成为80bit

前:

00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 010000

后:

00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 01000000

距离104还差24bit,使用Pad bytes继续填充

236 17
11101100 00010001

00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 01000000 11101100 00010001 11101100

236 - 17 - 236 - 17 如此循环下去,直到填满为止,对应的十进制为

32,91,11,120,209,114,220,77,67,64,236,17,236

数据纠错编码

  • 数据分组

  • Reed-Solomon算法,包含多项式、伽罗瓦群论、对数、XOR计算等组合方法生成

    image

    image

image

根据算法产生的纠错码为

168 72 22 82 217 54 156 0 46 15 180 122 16

合起来为

Col 1 Col 2 Col 3 Col 4 Col 5 Col 6 Col 7 Col 8 Col 9 Col 10 Col 11 Col 12 Col 13
Block 1 32 91 11 120 209 114 220 77 67 64 236 17 236
Block 2
ECC1 168 72 22 82 217 54 156 0 46 15 180 122 16
ECC2

内容连起来,转换为二进制,类似于

1
01000011111101101011011001000110

尾部添加0

不同的版本在末尾添加0补全

QR Version Required Remainder Bits
1 0
2 7
3 7
4 7
5 7
6 7
7 0
8 0
9 0
10 0
11 0
12 0
13 0
14 3
15 3
16 3
17 3
18 3
19 3
20 3
21 4
22 4
23 4
24 4
25 4
26 4
27 4
28 3
29 3
30 3
31 3
32 3
33 3
34 3
35 0
36 0
37 0
38 0
39 0
40 0

在这里我们用第一版,不加零

生成矩阵

image

image

image

添加分隔线

img

img

添加对齐图案

img

version 2及其以上需要这个图案,经过查表可以得知,以左上角为原点,可以摆放四个位置,(6, 6), (6, 18), (18, 6) and (18, 18),不能遮挡,故右下角合格

INCORRECT

img

CORRECT

img

img

添加Timing Patterns

imgimg

img

开始和结束均为黑色

黑色模块和数据保留区

imgimg

左下角黑点 Dark Module和蓝色区域部分Reserved Areas

版本数据区域

imgimg

version 7及其以上必须包含版本信息,两个蓝色区域

添加文本数据

img

img

img

如果遇到了阻挡,绕过去

img

如果遇到了垂直的Timing Pattern,跳过去到下一列

img

Data Masking

为什么需要masking,因为要减少复杂度,提升机器的识别率

什么是masking

  • 黑白切换

Mask方法

  • 只mask数据区域

Mask种类

Mask Number If the formula below is true for a given row/column coordinate, switch the bit at that coordinate
0 (row + column) mod 2 == 0
1 (row) mod 2 == 0
2 (column) mod 3 == 0
3 (row + column) mod 3 == 0
4 ( floor(row / 2) + floor(column / 3) ) mod 2 == 0
5 ((row * column) mod 2) + ((row * column) mod 3) == 0
6 ( ((row * column) mod 2) + ((row * column) mod 3) ) mod 2 == 0
7 ( ((row + column) mod 2) + ((row * column) mod 3) ) mod 2 == 0

寻找最佳Mask

每一种mask加上去后进行四种惩罚算法验证,得分最低者为最合适的mask

  • The first rule gives the QR code a penalty for each group of five or more same-colored modules in a row (or column).
  • The second rule gives the QR code a penalty for each 2x2 area of same-colored modules in the matrix.
  • The third rule gives the QR code a large penalty if there are patterns that look similar to the finder patterns.
  • The fourth rule gives the QR code a penalty if more than half of the modules are dark or light, with a larger penalty for a larger difference.

这里举第一种惩罚算法为例

imgimg

img

350得分最低,选择第一种mask

添加格式信息

纠错级别有四个 L M Q H,Maks有八种,一共32种组合

格式信息是一个15-bit长的字符串

前5个bit包含纠错版本(2-bit)和mask版本(3-bit)

Error Correction Level Bits Integer Equivalent
L 01 1
M 00 0
Q 11 3
H 10 2
Mask Number If the formula below is true for a given row/column coordinate, switch the bit at that coordinate
0 (row + column) mod 2 == 0
1 (row) mod 2 == 0
2 (column) mod 3 == 0
3 (row + column) mod 3 == 0
4 ( floor(row / 2) + floor(column / 3) ) mod 2 == 0
5 ((row * column) mod 2) + ((row * column) mod 3) == 0
6 ( ((row * column) mod 2) + ((row * column) mod 3) ) mod 2 == 0
7 ( ((row + column) mod 2) + ((row * column) mod 3) ) mod 2 == 0

11000,剩下的十位重新使用Reed-Solomon算法生成ECC code,填进去二维码蓝色区域

The layout of format string bits, where 14 is the most significant bit and 0 is the least significant bit

无论哪个版本,格式信息总是在红色的区域

imgimg

生成版本信息

version 7及其以上版本,必须包含18bit长度的版本信息,6-bit表示版本号,12-bit代表纠错码,同样的算法生成

imgimg

蓝色区域,3*6格子,下图是一个version 7示例

img

顺序是从右下到左上填充

00 01 02
03 04 05
06 07 08
09 10 11
12 13 14
15 16 17
17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 0 0 1 1 1 1 1 0 0 1 0 0 1 0 1 0 0

添加合适mask(上面已经叙述过)

添加quiet zone

最终生成 HELLO WORLD 二维码,1-Q,Alphanumeric

img

完。

image

附录:

条形码:一维码,一种包含物料详情的机读型的光学标签

image

ASCII Table:

image

image

在线进制转换网站 https://tool.lu/hexconvert/

参考:https://www.nayuki.io/page/creating-a-qr-code-step-by-step

https://en.wikipedia.org/wiki/QR_code

https://www.explainthatstuff.com/how-data-matrix-codes-work.html

https://www.thonky.com/qr-code-tutorial/introduction