- 텍스트가 QR 코드로 바뀌는 내부 과정을 0~9단계 시각화로 따라가며, Nayuki QR Code generator library의 동작 원리를 확인할 수 있음
- 예시 입력
Hello, world! 123은 17개 Unicode 코드 포인트로 분석되고, Numeric·Alphanumeric·Kanji가 아닌 Byte 모드로 인코딩됨 - 모드 비트, 문자 수, 세그먼트 데이터, 종료 비트를 이어 붙인 결과 19개 데이터 코드워드가 만들어져 Version 1의 ECC L 용량에 들어맞음
- Version 1 QR 코드는 1개 블록에 데이터 코드워드 19개와 Reed–Solomon ECC 코드워드 7개를 붙인 뒤, 고정 패턴과 데이터 모듈을 배치함
- 8개 마스크의 패널티를 비교해 총점이 가장 낮은 Mask pattern 3을 선택하며, 최종 결과가 단순 인코딩이 아니라 품질 평가까지 거쳐 정해짐
데모의 목적과 입력 처리
- 이 웹 애플리케이션은 텍스트 문자열이 QR 코드로 인코딩되는 과정을 단계별로 시각화함
- 페이지는 QR Code generator library의 내부 동작을 이해할 수 있도록 인코딩 과정을 풀어 보여줌
- 사용자 입력 항목은 텍스트 문자열, 오류 정정 수준, 최소 Version 강제, 마스크 패턴 강제로 구성됨
0단계: Unicode 문자 분석
- 예시 문자열은
Hello, world! 123이며, 입력 텍스트의 코드 포인트 수는 17개임 - 각 문자는 Numeric, Alphanumeric, Byte, Kanji 모드에서 인코딩 가능한지 검사됨
- 전체 문자열의 모드별 인코딩 가능 여부는 다음과 같음
- Numeric: 불가능
- Alphanumeric: 불가능
- Byte: 가능
- Kanji: 불가능
- 전체 문자를 담기 위해 선택된 세그먼트 모드는 Byte임
1단계: 데이터 세그먼트 생성
- 각 문자는 비트열로 변환됨
- Numeric 및 Alphanumeric 모드에서는 연속 문자를 묶어서 인코딩함
- Byte 모드에서는 문자 하나가 8, 16, 24, 32비트 중 하나를 생성함
- 예시에서는 각 문자의 16진수 값이 8비트로 변환됨
H:48→01001000e:65→011001011:31→001100012:32→001100103:33→00110011
- 데모 프로그램은 단순화를 위해 항상 단일 세그먼트를 만듦
- 전체 비트 길이를 줄이는 최적 분할 방식은 optimal text segmentation for QR codes에서 따로 다룸
2단계: Version 번호 맞추기
- 세그먼트 목록을 표현하는 데 필요한 전체 비트 길이는 Version 범위에 따라 달라짐
- Version 1~9: 148비트, 19 코드워드
- Version 10~26: 156비트, 20 코드워드
- Version 27~40: 156비트, 20 코드워드
- 코드워드는 8비트, 즉 1바이트로 정의됨
- QR 코드의 데이터 코드워드 용량은 Version과 오류 정정 수준에 따라 달라짐
- 예시 입력은 선택된 오류 정정 수준에서 Version 1에 들어맞음
- 최종 선택된 Version 번호는 1임
3단계: 세그먼트 연결, 패딩, 코드워드 생성
- 여러 비트 문자열을 이어 붙여 데이터 비트열을 만듦
- Segment 0 mode:
0100, 4비트 - Segment 0 count:
00010001, 8비트 - Segment 0 data: 136비트
- Terminator:
0000, 4비트
- Segment 0 mode:
- 누적 비트 수는 152비트임
- 예시에서는 Bit padding과 Byte padding이 모두 0비트임
- 전체 데이터 코드워드 바이트는 8비트 단위로 나뉘어 16진수로 표시됨
41 14 86 56 C6 C6 F2 C2 07 76 F7 26 C6 42 12 03 13 23 30
4단계: 블록 분할, ECC 추가, 인터리브
- 예시의 블록 통계는 다음과 같음
- 데이터 코드워드 수: 19
- 블록 수: 1
- 짧은 블록당 데이터 코드워드: 19
- 긴 블록당 데이터 코드워드: 해당 없음
- 블록당 ECC 코드워드: 7
- 짧은 블록 수: 1
- 긴 블록 수: 0
- 데이터 코드워드 시퀀스를 짧은 블록과 긴 블록으로 나누고, 각 블록 끝에 ECC 코드워드를 계산해 붙임
- Reed–Solomon 오류 정정 코드 계산의 수학적 과정은 길고 지루하며 흥미롭지 않다는 이유로 생략됨
- 최종 코드워드 시퀀스는 데이터와 ECC 코드워드를 인터리브해 구성됨
41 14 86 56 C6 C6 F2 C2 07 76 F7 26 C6 42 12 03 13 23 30 85 A9 5E 07 0A 36 C9
- 지그재그 스캔에 그릴 최종 비트열도 이 코드워드 시퀀스에서 생성됨
5~6단계: 고정 패턴과 코드워드 배치
- 고정 패턴 단계에서는 행 6과 열 6에 timing pattern을 그림
- 세 모서리에는 separator를 포함해 각각 8×8 finder pattern을 배치함
- finder 주변에는 임시 dummy format bits가 들어감
- 코드워드 배치 단계에서는 오른쪽 아래 모서리에서 시작하는 지그재그 스캔을 계산함
- 지그재그 스캔은 기능 모듈(function module)을 건너뛰고 아직 채워지지 않은 모듈을 방문함
- 데이터, ECC, remainder 모듈은 최종 코드워드 비트값과 지그재그 순서에 따라 그려짐
- 예시로 16진수 코드워드
C5는 이진수11000101이며,[dark, dark, light, light, light, dark, light, dark]모듈 시퀀스를 생성함
7~9단계: 마스크 적용과 패널티 계산
- 각 마스크 패턴은 비기능 모듈(non-function module)에만 영향을 줌
- 마스크는 데이터, ECC, remainder 모듈에 XOR로 적용됨
- 실제 format bits는 finder 주변에 그려짐
- 패널티 탐색은 다음 요소를 검사함
- 같은 색 모듈이 5개 이상 이어지는 가로 run
- 같은 색 모듈이 5개 이상 이어지는 세로 run
- 같은 색의 2×2 box
- 가로 finder-like pattern
- 세로 finder-like pattern
- 어두운 모듈과 밝은 모듈의 균형
- 예시 QR 코드의 크기와 색상 비율은 다음과 같음
- 한 변 길이: 21
- 전체 모듈: 441
- 밝은 모듈: 221
- 어두운 모듈: 220
- 어두운 모듈 비율: 49.887%
- 절반 대비 편차: −0.113%
- 8개 마스크의 총 패널티는 다음과 같음
- Mask 0: 1204
- Mask 1: 1134
- Mask 2: 1084
- Mask 3: 1081
- Mask 4: 1121
- Mask 5: 1100
- Mask 6: 1189
- Mask 7: 1137
- 가장 낮은 총 패널티를 받은 마스크는 Mask pattern 3임
소스 코드
- 웹 애플리케이션의 TypeScript 소스 코드는 file 0, file 1로 제공됨
- 컴파일된 JavaScript 코드는 creating-qr-code-steps.js에서 볼 수 있음