Mercurial > core / lisp/lib/dat/qrcode.lisp
changeset 698: |
96958d3eb5b0 |
parent: |
2596311106ae
|
author: |
Richard Westhaver <ellis@rwest.io> |
date: |
Fri, 04 Oct 2024 22:04:59 -0400 |
permissions: |
-rw-r--r-- |
description: |
fixes |
1 ;;; dat/qrcode.lisp --- QR Code formats 3 ;; see https://github.com/jnjcc/cl-qrencode 6 (in-package :dat/qrcode) 8 ;;;; Copyright (c) 2011-2014 jnjcc, Yste.org. All rights reserved. 10 (defun read-file-content (fpath) 11 (with-open-file (fp fpath) 12 (let ((content (make-string (file-length fp)))) 13 (read-sequence content fp) 16 ;;;; Galois Field with primitive element 2, as used by Reed-Solomon code 19 ((power :initform nil :initarg :power :reader gf-power 20 :documentation "Galois Field GF(2^POWER)") 21 (prime-poly :initform nil :initarg :ppoly :reader prime-poly 22 :documentation "prime polynomial") 23 (order :initform nil :reader gf-order) 24 (exp-table :initform nil) 25 (log-table :initform nil))) 27 (defmethod initialize-instance :after ((gf galois) &rest args) 28 (declare (ignore args)) 29 (setf (slot-value gf 'order) (ash 1 (slot-value gf 'power))) 30 (let* ((order (gf-order gf)) 31 (ppoly (prime-poly gf)) 32 ;; 2^0 = 1 && (log 0) = -1 33 (exptab (make-array order :initial-element 1)) 34 (logtab (make-array order :initial-element -1))) 37 (setf (aref exptab i) (* (aref exptab (- i 1)) 2)) 38 (when (>= (aref exptab i) order) 40 (boole boole-and (- order 1) 41 (boole boole-xor (aref exptab i) ppoly)))) 42 (setf (aref logtab (aref exptab i)) i)) 43 (setf (aref logtab 1) 0) 44 (setf (slot-value gf 'exp-table) exptab) 45 (setf (slot-value gf 'log-table) logtab))) 48 (defgeneric gf-exp (gf pow) 49 (:documentation "2^POW under Galois Field GF")) 50 (defgeneric gf-log (gf value) 51 (:documentation "VALUE should be within range [0, 2^POW - 1]")) 53 (defmethod gf-exp ((gf galois) pow) 54 (let* ((sz (- (gf-order gf) 1)) 56 (aref (slot-value gf 'exp-table) idx))) 58 (defmethod gf-log ((gf galois) value) 59 (let* ((sz (gf-order gf)) 61 (aref (slot-value gf 'log-table) idx))) 63 ;;; Galois Field arithmetic 64 (defgeneric gf-add (gf a b)) 65 (defgeneric gf-subtract (gf a b)) 66 (defgeneric gf-multiply (gf a b)) 67 (defgeneric gf-divide (gf a b)) 69 (defmethod gf-add ((gf galois) a b) 70 (boole boole-xor a b)) 72 (defmethod gf-subtract ((gf galois) a b) 73 (boole boole-xor a b)) 75 (defmethod gf-multiply ((gf galois) a b) 76 (let ((sum (+ (gf-log gf a) (gf-log gf b)))) 79 (defmethod gf-divide ((gf galois) a b) 81 (error "divide by zero")) 84 (let ((sub (- (gf-log gf a) (gf-log gf b)))) 87 ;;; open-paren at beg of line confuses `slime-compile-defun` which uses 88 ;;; elisp function `beginning-of-defun`, which in turn involves 89 ;;; backward-searching open-paren at beg of line 90 ;;; there seems to be no easy way to fix this problem 91 ;; with an extra leading '\', docstring is kind of ulgy now, though 92 (defmacro with-gf-accessors (accessors gf &body body) 93 "shortcuts for gf-exp & gf-log, usage: 94 \(with-gf-accessors ((gfexp gf-exp)) *gf-instance* ...)" 95 `(labels ,(mapcar (lambda (acc-entry) 96 (let ((acc-name (car acc-entry)) 97 (method-name (cadr acc-entry))) 99 (,method-name ,gf a)))) 103 (defmacro with-gf-arithmetics (ariths gf &body body) 104 "shortcuts for gf-add, gf-subtract, gf-multiply & gf-divide, usage: 105 \(with-gf-arithmetics ((gf+ gf-add)) *gf-instance* ...)" 106 `(labels ,(mapcar (lambda (arith-entry) 107 (let ((arith-name (car arith-entry)) 108 (method-name (cadr arith-entry))) 110 (,method-name ,gf a b)))) 114 (defmacro with-gf-shortcuts (accessors ariths gf &body body) 115 "combined with-gf-accessors & with-gf-arithmetics, usage: 116 \(with-gf-shortcuts ((gflog gf-log)) ((gf* gf-multiply)) *gf-instance* ...)" 118 (mapcar (lambda (acc-entry) 119 (let ((acc-name (car acc-entry)) 120 (method-name (cadr acc-entry))) 122 (,method-name ,gf a)))) 124 (mapcar (lambda (arith-entry) 125 (let ((arith-name (car arith-entry)) 126 (method-name (cadr arith-entry))) 128 (,method-name ,gf a b)))) 132 ;;;; Bose-Chaudhuri-Hocquenghem (BCH) error correction code 134 ;;; Polynomial (using list) arithmetics 135 ;;; by polynomial list (3 2 1), we mean 3*x^2 + 2*x + 1 136 (defun poly-ash (poly s) 137 "shift left POLY by S" 138 (declare (type list poly)) 139 (append poly (make-list s :initial-element 0))) 140 (defun poly-multiply (poly b &optional (op #'*)) 141 "multiply B on every element of POLY using OP" 142 (labels ((mult (elem) 143 (funcall op elem b))) 144 (mapcar #'mult poly))) 145 (defun poly-substract (lhs rhs &optional (op #'-)) 146 (labels ((sub (elem1 elem2) 147 (funcall op elem1 elem2))) 148 (mapcar #'sub lhs rhs))) 149 (defun poly-mod (msg gen rem &optional (sub #'poly-substract) (mul #'poly-multiply)) 150 "MSG % GEN, with REM remainders" 151 (labels ((cdrnzero (msg rem) 152 (do ((head msg (cdr head))) 153 ((or (null head) (<= (length head) rem) (/= (car head) 0)) head) 155 (do ((m (poly-ash msg rem) (cdrnzero m rem))) 156 ((<= (length m) rem) m) 157 (let* ((glen (length gen)) 158 (sft (- (length m) glen)) 159 ;; LEAD coffiecient of message polynomial 161 (setf m (funcall sub m (poly-ash (funcall mul gen lead) sft))))))) 164 ((k :initform nil :initarg :k 165 :documentation "# of data codewords") 166 (ec :initform nil :initarg :ec 167 :documentation "# of error correction codewords"))) 170 (poly-multiply poly b)) 171 (defun bch- (lhs rhs) 173 (boole boole-xor a b))) 174 (poly-substract lhs rhs #'xor))) 175 (defun bch-xor (lhs rhs) 177 (boole boole-xor a b))) 178 (mapcar #'xor lhs rhs))) 179 (defun bch% (msg gen rem) 180 (poly-mod msg gen rem #'bch- #'bch*)) 182 (defgeneric bch-ecc (bch msgpoly genpoly) 183 (:documentation "do bch error correction under BCH(K+EC, K)")) 185 (defmethod bch-ecc ((bch bch-ecc) msg gen) 186 (with-slots (k ec) bch 187 (unless (= (length msg) k) 188 (error "wrong msg length, expect: ~A; got: ~A~%" k (length msg))) 191 ;;; As used by format information ecc & version information ecc respectively 192 ;;; BCH(15, 5) & BCH(18, 6) 193 (let ((fi-ecc (make-instance 'bch-ecc :k 5 :ec 10)) 194 ;; format information generator polynomial 195 ;; x^10 + x^8 + x^5 + x^4 + x^2 + x + 1 196 (fi-gpoly '(1 0 1 0 0 1 1 0 1 1 1)) 197 (fi-xor '(1 0 1 0 1 0 0 0 0 0 1 0 0 1 0))) 198 (defun format-ecc (level mask-ind) 199 (let ((seq (append (level-indicator level) 200 (mask-pattern-ref mask-ind)))) 201 (bch-xor (append seq (bch-ecc fi-ecc seq fi-gpoly)) 204 (let ((vi-ecc (make-instance 'bch-ecc :k 6 :ec 12)) 205 ;; version information generator polynomial 206 ;; x^12 + x^11 + x^10 + x^9 + x^8 + x^5 + x^2 + 1 207 (vi-gpoly '(1 1 1 1 1 0 0 1 0 0 1 0 1))) 208 (defun version-ecc (version) 209 (let ((seq (decimal->bstream version 6))) 210 (append seq (bch-ecc vi-ecc seq vi-gpoly))))) 213 ((k :initform nil :initarg :k 214 :documentation "# of data codewords") 215 (ec :initform nil :initarg :ec 216 :documentation "# of error correction codewords") 217 (gpoly :initform nil :reader gpoly 218 :documentation "with EC, we calculate generator poly immediately"))) 220 ;;; Reed-Solomon code uses GF(2^8) with prime polynomial 285, 221 ;;; or 1,0001,1101, or (x^8 + x^4 + x^3 + x^2 + 1) 222 (let ((gf256 (make-instance 'galois :power 8 :ppoly 285))) 223 ;; Polynomial arithmetics under GF(2^8), as used by Reed-Solomon ecc 225 "multiply B on every element of POLY under GF(2^8)" 226 (with-gf-arithmetics ((gf* gf-multiply)) gf256 227 (poly-multiply poly b #'gf*))) 229 (with-gf-arithmetics ((gf- gf-subtract)) gf256 230 (poly-substract lhs rhs #'gf-))) 231 (defun rs% (msg gen rem) 232 (poly-mod msg gen rem #'rs- #'rs*)) 234 (defmethod initialize-instance :after ((rs rs-ecc) &rest args) 235 (declare (ignore args)) 236 (setf (slot-value rs 'gpoly) (gen-poly rs))) 238 (defgeneric gen-poly (rs)) 239 (defmethod gen-poly ((rs rs-ecc)) 240 "Generator Polynomial: (x-a^0) * (x-a^1) * ... * (x-a^(ec-1))" 242 (let* ((size (+ ec 1)) 243 (poly (make-list size :initial-element nil))) 244 (with-gf-shortcuts ((gfexp gf-exp)) ((gf+ gf-add) (gf* gf-multiply)) gf256 249 (setf (nth i poly) 1) 250 (do ((j (- i 1) (1- j))) 252 (if (not (= (nth j poly) 0)) 254 (gf+ (nth (- j 1) poly) 255 (gf* (nth j poly) (gfexp (- i 1))))) 256 (setf (nth j poly) (nth (- j 1) poly)))) 257 (setf (nth 0 poly) (gf* (nth 0 poly) (gfexp (- i 1)))))) 260 (defgeneric gen-poly-gflog (rs)) 261 (defgeneric ecc-poly (rs msg)) 263 (defmethod gen-poly-gflog ((rs rs-ecc)) 264 (with-gf-accessors ((gflog gf-log)) gf256 265 ;; GPOLY already calculated when making new instance 266 (mapcar #'gflog (gpoly rs)))) 268 (defmethod ecc-poly ((rs rs-ecc) msg-poly) 269 "Error Correction codewords Polynomial for MSG-POLY" 270 (with-slots (k ec gpoly) rs 271 (unless (= (length msg-poly) k) 272 (error "wrong msg-poly length, expect: ~A~%" k)) 273 (rs% msg-poly gpoly ec)))) 277 :numeric :alnum :byte :kanji 278 ;; Extended Channel Interpretation, Structured Append, FNC1 279 :eci :structured :fnc1)) 281 (defun mode-indicator (mode) 282 (declare (type qr-mode mode)) 284 (:numeric '(0 0 0 1)) ; "0001" 285 (:alnum '(0 0 1 0)) ; "0010" 286 (:byte '(0 1 0 0)) ; "0100" 287 (:kanji '(1 0 0 0)) ; "1000" 288 (:eci '(0 1 1 1)) ; "0111" 289 (:structured '(0 0 1 1)) ; "0011" 290 (:fnc1 '(0 1 0 1)))) ; FIXME: "0101" & "1001" 292 (defun terminator (bstream version level) 294 (let* ((nbits (length bstream)) 295 (diff (- (* (data-words-capacity version level) 8) 298 ((< diff 0) (error "you serious about this?!")) 299 ((<= diff 4) (make-list diff :initial-element 0)) 300 (t (make-list 4 :initial-element 0))))) 302 (defun byte-value (mode byte) 303 "BYTE value under MODE" 304 (declare (type qr-mode mode)) 307 (and (<= #x30 byte #x39) 311 ((<= #x30 byte #x39) (- byte #x30)) ; 0-9 312 ((<= #x41 byte #x5A) (+ (- byte #x41) 10)) ; A-Z 313 ((= byte #x20) 36) ; SP 314 ((= byte #x24) 37) ; $ 315 ((= byte #x25) 38) ; % 316 ((= byte #x2A) 39) ; * 317 ((= byte #x2B) 40) ; + 318 ((= byte #x2D) 41) ; - 319 ((= byte #x2E) 42) ; . 320 ((= byte #x2F) 43) ; / 321 ((= byte #x3A) 44) ; : 323 ((:byte :kanji) byte))) 325 (defun kanji-word-p (word) 326 "(kanji-p, kanji-range: {0, 1})" 328 ((<= #x8140 word #x9ffc) (values t 0)) 329 ((<= #xe040 word #xebbf) (values t 1)) 330 (t (values nil nil)))) 332 (defun starts-kanji-p (bytes) 333 "(BYTES starts with kanji-p, kanji word value, kanji-range: {0, 1})" 334 (declare (type list bytes)) 335 (let* ((first (car bytes)) 336 (second (cadr bytes)) 337 (word (and second (+ (ash first 8) second)))) 338 (if (and first second) 339 (multiple-value-bind (kanji-p range) 341 (values kanji-p word range)) 342 (values nil nil nil)))) 344 (defun xor-subset-of (bytes) 345 "exclusive subset of first unit of BYTES. 346 as for unit, one byte for :numeric, :alnum; two bytes for :kanji" 347 (declare (type list bytes)) 348 (let* ((first (car bytes))) 350 ((null first) :unknown) 351 ((byte-value :numeric first) :numeric) 352 ((byte-value :alnum first) :alnum) 353 ;; excluding reserved values 80-9F & E0-FF 354 ((and (not (<= #x80 first #x9F)) 355 (not (<= #xE0 first #xFF))) 357 ((starts-kanji-p bytes) 360 (defclass qr-input () 362 :initform nil :initarg :bytes :reader bytes :type list 363 :documentation "list of bytes to be encoded") 365 :initform 1 :initarg :version :reader version 366 :documentation "version of qr symbol, adapted according to BYTES") 367 (ec-level ; cannot be NIL 368 :initform :level-m :initarg :ec-level :reader level :type ecc-level) 370 :initform nil :initarg :mode :reader mode :type (or null qr-mode) 371 :documentation "if supplied, we force all BYTES to be under MODE, 372 therefore, unless you know exactly what you are doing, leave this NIL") 374 :initform 0 :accessor cur-byte 375 :documentation "index of BYTES during data analysis") 377 :initform nil :accessor segments :type list 379 "list of list, of the form ((:mode1 byte ...) (:mode2 byte ...) ...)") 381 :initform nil :reader bstream :type list 382 :documentation "list of 0-1 values after encoding SEGMENTS") 384 :initform nil :reader blocks :type list 385 :documentation "list of list, of the form ((codeword ...) (codeword ...) ...) 386 after converting BSTREAM to codewords") 387 (ecc-blocks ; error correction blocks 388 :initform nil :reader ecc-blocks :type list 389 :documentation "list of list, ec codewords corresponding to BLOCKS") 391 :initform nil :reader message :type list 392 :documentation "list of codewords from BLOCKS & ECC-BLOCKS, 393 interleaving if neccessary") 395 :initform nil :accessor matrix 396 :documentation "raw QR code symbol (without masking) as matrix"))) 398 (defmethod initialize-instance :after ((input qr-input) &rest args) 399 (declare (ignore args)) 400 (validate-and-analysis input)) 403 (defgeneric validate-and-analysis (input) 404 (:documentation "adapt VERSION according to BYTES, and fill SEGMENTS slot")) 406 (defgeneric data-encoding (input) 407 (:documentation "encode SEGMENTS into BSTREAM slot")) 408 ;;; 2) Error correction coding 409 (defgeneric ec-coding (input) 410 (:documentation "split BSTREAM into BLOCKS, do rs-ecc, and fill ECC-BLOCKS")) 411 ;;; 3) Structure final message 412 (defgeneric structure-message (input) 413 (:documentation "interleaving BLOCKS and ECC-BLOCKS into MSG-CODEWORDS")) 414 ;;; 4) Codeword placement in matrix, a.k.a, raw QR code symbol 415 (defgeneric module-placement (input) 416 (:documentation "write MSG-CODEWORDS into the raw (without masking) MATRIX")) 417 ;;; 5) Data masking & Format information 418 (defgeneric data-masking (input) 419 (:documentation "mask MATRIX with best pattern, generate the final symbol")) 421 (defgeneric data-analysis (input) 422 (:documentation "BYTES -> SEGMETS, switch bewteen modes as necessary to 423 achieve the most efficient conversion of data")) 424 (defgeneric redo-data-analysis (input) 425 (:documentation "VERSION changed, reset CUR-BYTE and redo data analysis")) 426 (defgeneric analyse-byte-mode (input &optional seg)) 427 (defgeneric analyse-alnum-mode (input &optional seg)) 428 (defgeneric analyse-numeric-mode (input &optional seg)) 429 (defgeneric analyse-kanji-mode (input &optional seg)) 430 (defgeneric append-cur-byte (input &optional seg) 431 (:documentation "append CUR-BYTE of BYTES into SEGMENTS")) 432 (defun mode-analyse-func (mode) 433 "put CUR-BYTE into MODE, and then look at following BYTES for new segment" 435 (:byte #'analyse-byte-mode) 436 (:alnum #'analyse-alnum-mode) 437 (:numeric #'analyse-numeric-mode) 438 (:kanji #'analyse-kanji-mode))) 440 (defmethod data-analysis ((input qr-input)) 441 (with-slots (mode cur-byte segments) input 442 (when mode ; MODE supplied 443 (let ((seg (append (list mode) (bytes input)))) 444 (setf cur-byte (length (bytes input))) 445 (setf segments (append segments (list seg)))) 446 (return-from data-analysis))) 447 (with-slots (bytes version segments) input 448 (let ((init-mode (select-init-mode bytes version))) 449 (funcall (mode-analyse-func init-mode) input)))) 451 (defmethod redo-data-analysis ((input qr-input)) 452 (with-slots (cur-byte segments) input 455 (data-analysis input))) 457 (defun select-init-mode (bytes version) 458 "optimization of bitstream length: select initial mode" 459 (declare (type list bytes)) 460 (let ((init-xor (xor-subset-of bytes))) 464 (case (xor-subset-of (nthcdr 2 bytes)) 465 ((:numeric :alnum) :kanji) 467 (let ((nunits (ecase (version-range version) 470 (if (every-unit-matches (nthcdr 3 bytes) 2 nunits :kanji) 475 (let ((nunits (ecase (version-range version) 477 ;; number of units (characters) match :alnum, followed by a :byte unit 478 (multiple-value-bind (n last-mode) (nunits-matches (cdr bytes) :alnum) 479 (if (and (< n nunits) (eq last-mode :byte)) 483 (let ((nbunits (ecase (version-range version) 485 (naunits (ecase (version-range version) 487 (multiple-value-bind (n last-mode) (nunits-matches (cdr bytes) :numeric) 488 (if (and (< n nbunits) (eq last-mode :byte)) 490 (if (and (< n naunits) (eq last-mode :alnum)) 494 ;;; UNIT: character under a certain mode, 495 ;;; a byte under :numeric :alnum & :byte, or a byte-pair under :kanji 496 (defun every-unit-matches (bytes usize nunits mode) 497 "if every unit of USZIE bytes (at most NUNITS unit) within BYTES matches MODE" 498 (declare (type list bytes) (type qr-mode mode)) 499 (when (>= (length bytes) (* usize nunits)) 501 (let ((b (nthcdr (* usize i) bytes))) 502 (unless (eq (xor-subset-of b) mode) 503 (return-from every-unit-matches nil)))) 504 (return-from every-unit-matches t))) 506 (defun nunits-matches (bytes mode) 507 "(number of units that matches MODE, and mode for the first unmatched unit)" 508 (declare (type list bytes) (type qr-mode mode)) 509 (let ((usize (ecase mode 510 ((:byte :alnum :numeric) 1) 511 ;; as for :kanji, 2 bytes forms a single unit 514 (do ((b bytes (nthcdr usize b))) 516 (not (eq (xor-subset-of b) mode))) 517 (values nunits (xor-subset-of b))) 520 (defmethod analyse-byte-mode ((input qr-input) &optional (seg '(:byte))) 521 (declare (type list seg)) 522 (setf seg (append-cur-byte input seg)) 524 (return-from analyse-byte-mode)) 525 (with-slots (bytes cur-byte version segments) input 526 (let* ((range (version-range version)) 527 (nkunits (ecase range ; number of :kanji units before more :byte 528 (0 9) (1 12) (2 13))) 529 (nanuits (ecase range ; number of :alnum units before more :byte 530 (0 11) (1 15) (2 16))) 531 (nmunits1 (ecase range ; number of :numeric units before more :byte 533 (nmunits2 (ecase range ; number of :numeric units before more :alnum 536 (multiple-value-bind (nmatches last-mode) 537 (nunits-matches (nthcdr cur-byte bytes) :kanji) 538 (and (>= nmatches nkunits) (eq last-mode :byte) 539 (setf switch-mode :kanji))) 541 (multiple-value-bind (nmatches last-mode) 542 (nunits-matches (nthcdr cur-byte bytes) :alnum) 543 (and (>= nmatches nanuits) (eq last-mode :byte) 544 (setf switch-mode :alnum)))) 546 (multiple-value-bind (nmatches last-mode) 547 (nunits-matches (nthcdr cur-byte bytes) :numeric) 549 (:byte (and (>= nmatches nmunits1) 550 (setf switch-mode :numeric))) 551 (:alnum (and (>= nmatches nmunits2) 552 (setf switch-mode :numeric)))))) 555 ;; current segment finished, add a new SWITCH-MODE segment 556 (setf segments (append segments (list seg))) 557 (setf seg (list switch-mode))) 558 (setf switch-mode :byte)) 559 (funcall (mode-analyse-func switch-mode) input seg)))) 561 (defmethod analyse-alnum-mode ((input qr-input) &optional (seg '(:alnum))) 562 (declare (type list seg)) 563 (setf seg (append-cur-byte input seg)) 565 (return-from analyse-alnum-mode)) 566 (with-slots (bytes cur-byte version segments) input 567 (let ((nmunits (ecase (version-range version) 568 (0 13) (1 15) (2 17))) 570 (when (>= (nunits-matches (nthcdr cur-byte bytes) :kanji) 1) 571 (setf switch-mode :kanji)) 573 (when (>= (nunits-matches (nthcdr cur-byte bytes) :byte) 1) 574 (setf switch-mode :byte))) 576 (multiple-value-bind (nmatches last-mode) 577 (nunits-matches (nthcdr cur-byte bytes) :numeric) 578 (and (>= nmatches nmunits) (eq last-mode :alnum) 579 (setf switch-mode :numeric)))) 582 (setf segments (append segments (list seg))) 583 (setf seg (list switch-mode))) 584 (setf switch-mode :alnum)) 585 (funcall (mode-analyse-func switch-mode) input seg)))) 587 (defmethod analyse-numeric-mode ((input qr-input) &optional (seg '(:numeric))) 588 (declare (type list seg)) 589 (setf seg (append-cur-byte input seg)) 591 (return-from analyse-numeric-mode)) 592 (with-slots (bytes cur-byte version segments) input 593 (let ((switch-mode nil)) 594 (when (>= (nunits-matches (nthcdr cur-byte bytes) :kanji) 1) 595 (setf switch-mode :kanji)) 597 (when (>= (nunits-matches (nthcdr cur-byte bytes) :byte) 1) 598 (setf switch-mode :byte))) 600 (when (>= (nunits-matches (nthcdr cur-byte bytes) :alnum) 1) 601 (setf switch-mode :alnum))) 604 (setf segments (append segments (list seg))) 605 (setf seg (list switch-mode))) 606 (setf switch-mode :numeric)) 607 (funcall (mode-analyse-func switch-mode) input seg)))) 609 (defmethod append-cur-byte ((input qr-input) &optional seg) 610 "if CUR-BYTE is the last byte, return nil" 611 (declare (type list seg)) 612 (with-slots (bytes cur-byte segments) input 613 (setf seg (append seg (list (nth cur-byte bytes)))) 615 (when (>= cur-byte (length bytes)) 616 (setf segments (append segments (list seg))) 618 (return-from append-cur-byte seg))) 620 (defmethod analyse-kanji-mode ((input qr-input) &optional (seg '(:kanji))) 621 (declare (type list seg)) 622 (with-slots (bytes cur-byte segments) input 623 (setf seg (append seg (nthcdr cur-byte bytes))) 624 (setf cur-byte (length bytes)) 625 (setf segments (append segments (list seg))))) 627 (defmethod validate-and-analysis ((input qr-input)) 628 (with-slots ((level ec-level) segments) input 629 (unless (<= 1 (version input) 40) 630 (error "version ~A out of bounds" (version input))) 632 ((<= (version input) prev)) 633 (setf prev (version input)) 634 (redo-data-analysis input) 635 (labels ((seg-bstream-len (seg) 636 (segment-bstream-length seg (version input)))) 637 (let* ((blen (reduce #'+ (mapcar #'seg-bstream-len segments) 639 (min-v (minimum-version prev (ceiling blen 8) level))) 641 (setf (slot-value input 'version) min-v) 642 (error "no version to hold ~A bytes" (ceiling blen 8)))))))) 644 (defmethod data-encoding ((input qr-input)) 645 (with-slots (version (level ec-level) segments) input 646 (labels ((seg->bstream (seg) 647 (segment->bstream seg version))) 648 (let* ((bs (reduce #'append (mapcar #'seg->bstream segments) 650 (tt (terminator bs version level)) 651 ;; connect bit streams in all segment, with terminator appended 652 (bstream (append bs tt))) 654 (setf bstream (append bstream (padding-bits bstream))) 655 ;; add pad codewords, finishes data encoding 656 (setf (slot-value input 'bstream) 658 (pad-codewords bstream version level))))))) 660 (defmethod ec-coding ((input qr-input)) 661 (with-slots (version (level ec-level) bstream) input 662 (let ((codewords (bstream->codewords bstream)) 665 ;; RS error correction obj for blk1 & blk2 668 (multiple-value-bind (ecc-num blk1 data1 blk2 data2) 669 (ecc-block-nums version level) 671 (setf rs1 (make-instance 'rs-ecc :k data1 :ec ecc-num))) 673 (setf rs2 (make-instance 'rs-ecc :k data2 :ec ecc-num))) 676 (append blocks (list (subseq codewords 0 data1)))) 677 (setf codewords (nthcdr data1 codewords))) 680 (append blocks (list (subseq codewords 0 data2)))) 681 (setf codewords (nthcdr data2 codewords))) 684 (append ecc-blocks (list (ecc-poly rs1 (nth i blocks)))))) 687 (append ecc-blocks (list (ecc-poly rs2 (nth (+ i blk1) blocks)))))) 688 (setf (slot-value input 'blocks) blocks) 689 (setf (slot-value input 'ecc-blocks) ecc-blocks))))) 691 (defmethod structure-message ((input qr-input)) 692 (with-slots (version (level ec-level) blocks ecc-blocks) input 694 (multiple-value-bind (ecc-num blk1 data1 blk2 data2) 695 (ecc-block-nums version level) 696 (declare (ignore ecc-num)) 697 (setf (slot-value input 'msg-codewords) 699 ;; interleave data blocks, data blocks may differ in length 700 (take-data-in-turn blocks blk1 data1 blk2 data2) 701 ;; we know error correction blocks are of the same length 702 (take-in-turn ecc-blocks))))))) 704 (defmethod module-placement ((input qr-input)) 705 (setf (matrix input) (make-matrix (version input))) 706 (with-slots (version msg-codewords matrix) input 707 ;; Function pattern placement 708 (function-patterns matrix version) 709 ;; Symbol character placement 710 (let ((rbits (remainder-bits version)) 712 (labels ((dec->byte (codeword) 713 (decimal->bstream codeword 8))) 714 (setf bstream (append (reduce #'append (mapcar #'dec->byte msg-codewords)) 715 ;; data capacity of _symbol_ does not divide by 8 716 (make-list rbits :initial-element 0)))) 717 (symbol-character bstream matrix version)))) 719 (defmethod data-masking ((input qr-input)) 720 "(masked matrix, mask pattern reference)" 721 (with-slots (version (level ec-level) matrix) input 722 (let ((modules (matrix-modules version))) 723 (multiple-value-bind (masked indicator) 724 (choose-masking matrix modules level) 725 (values masked (mask-pattern-ref indicator)))))) 727 (defun decimal->bstream (dec nbits) 728 "using NBITS bits to encode decimal DEC" 735 (defun bstream->decimal (bstream nbits) 736 (declare (type list bstream)) 737 (let ((nbits (min nbits (length bstream))) 740 (setf dec (+ (* dec 2) (nth i bstream)))) 744 (defun group->decimal (values ndigits) 745 "digit groups of length NDIGITS (1, 2 or 3) to decimal" 746 (declare (type list values)) 749 (2 (+ (* (nth 0 values) 10) (nth 1 values))) 750 (3 (+ (* (nth 0 values) 100) (* (nth 1 values) 10) (nth 2 values))))) 751 (defun final-digit-bits (n) 752 "the final one or two digits are converted to 4 or 7 bits respectively" 755 (defun numeric->bstream (bytes) 756 (declare (type list bytes)) 757 (labels ((num-value (byte) 758 (byte-value :numeric byte))) 759 (let ((values (mapcar #'num-value bytes)) 761 (do ((v values (nthcdr 3 v))) 764 (1 ; only 1 digits left 766 (append bstream (decimal->bstream (group->decimal v 1) 767 (final-digit-bits 1))))) 768 (2 ; only 2 digits left 770 (append bstream (decimal->bstream (group->decimal v 2) 771 (final-digit-bits 2))))) 772 (otherwise ; at least 3 digits left 775 (decimal->bstream (group->decimal v 3) 10))))))))) 778 (defun pair->decimal (values num) 779 "alnum pairs of length NUM (1 or 2) to decimal" 780 (declare (type list values)) 783 (2 (+ (* (nth 0 values) 45) (nth 1 values))))) 784 (defun alnum->bstream (bytes) 785 (declare (type list bytes)) 786 (labels ((alnum-value (byte) 787 (byte-value :alnum byte))) 788 (let ((values (mapcar #'alnum-value bytes)) 790 (do ((v values (nthcdr 2 v))) 793 (1 ; only 1 alnum left 796 (decimal->bstream (pair->decimal v 1) 6)))) 797 (otherwise ; at least 2 alnum left 800 (decimal->bstream (pair->decimal v 2) 11))))))))) 803 (defun byte->bstream (bytes) 804 (declare (type list bytes)) 805 (labels ((join (prev cur) 806 (append prev (decimal->bstream (byte-value :byte cur) 8)))) 807 (reduce #'join bytes :initial-value nil))) 810 (defun kanji->decimal (word range) 811 (let ((subtractor (ecase range 814 (decf word subtractor) 815 (setf word (+ (* (ash word -8) #xc0) 816 (boole boole-and word #xff))))) 817 (defun kanji->bstream (bytes) 818 (declare (type list bytes)) 819 (labels ((kanji-value (byte) 820 (byte-value :kanji byte))) 821 (let ((values (mapcar #'kanji-value bytes)) 824 (do ((v values (nthcdr delta v))) 827 (1 ; only 1 byte left 829 (append bstream (decimal->bstream (car v) 13))) 831 (otherwise ; at least 2 bytes left 832 (multiple-value-bind (kanji-p word range) (starts-kanji-p v) 837 (decimal->bstream (kanji->decimal word range) 842 (append bstream (decimal->bstream (car v) 13))) 843 (setf delta 1)))))))))) 846 (defun eci->bstream (bytes) 848 (declare (ignore bytes)) 849 (error "eci->bstream: TODO...")) 851 (defun bstream-trans-func (mode) 853 (:numeric #'numeric->bstream) 854 (:alnum #'alnum->bstream) 855 (:byte #'byte->bstream) 856 (:kanji #'kanji->bstream))) 858 (defun kanji-bytes-length (bytes) 859 (declare (type list bytes)) 862 (do ((b bytes (nthcdr step b))) 864 (if (starts-kanji-p b) 869 (defun bytes-length (bytes mode) 870 "number of data characters under MODE" 871 (declare (type list bytes) (type qr-mode mode)) 873 ((:numeric :alnum :byte) (length bytes)) 874 (:kanji (kanji-bytes-length bytes)))) 876 (defun segment-bstream-length (segment version) 877 "bit stream length of SEGMENT (:mode b0 b1 ...) under VERSION" 878 (declare (type list segment)) 879 (let* ((mode (car segment)) 880 (bytes (cdr segment)) 882 (c (char-count-bits version mode)) 883 (d (bytes-length bytes mode)) 885 ;; M = number of bits in mode indicator 886 ;; C = number of bits in character count indicator 887 ;; D = number of input data characters 890 (setf r (final-digit-bits (mod d 3))) 891 ;; B = M + C + 10 * (D / 3) + R 892 (+ m c (* 10 (floor d 3)) r)) 895 ;; B = M + C + 11 * (D / 2) + 6 * (D % 2) 896 (+ m c (* 11 (floor d 2)) (* 6 r))) 901 ;; B = M + C + 13 * D 904 (defun segment->bstream (segment version) 905 "SEGMENT (:mode b0 b1 ...) to bit stream under VERSION" 906 (declare (type list segment)) 907 (let* ((mode (car segment)) 908 (bytes (cdr segment)) 909 (len (bytes-length bytes mode)) 910 (n (char-count-bits version mode)) 912 (append bstream (mode-indicator mode) 913 (decimal->bstream len n) ; character count indicator 914 (funcall (bstream-trans-func mode) bytes)))) 916 (defun padding-bits (bstream) 917 "add padding bits so that BSTREAM ends at a codeword boundary" 918 (multiple-value-bind (quot rem) (ceiling (length bstream) 8) 919 (declare (ignore quot)) 920 (make-list (- rem) :initial-element 0))) 922 (defun pad-codewords (bstream version level) 923 "add pad codewords (after adding padding-bits) to fill data codeword capacity" 924 (let ((pad-words '((1 1 1 0 1 1 0 0) 926 (pad-len (- (data-words-capacity version level) 927 (/ (length bstream) 8))) 930 (setf ret (append ret (nth (mod i 2) pad-words)))) 933 (defun bstream->codewords (bstream) 934 "convert bstream into codewords, as coefficients of the terms of a polynomial" 935 (do ((b bstream (nthcdr 8 b)) 938 (setf codewords (append codewords (list (bstream->decimal b 8)))))) 940 (defun take-in-turn (blks) 941 "taking codewords from each block (bound by minimum length) in turn" 942 (reduce #'append (apply #'mapcar #'list blks))) 944 (defun take-data-in-turn (blocks blk1 data1 blk2 data2) 945 "taking data words from each block (might have different length) in turn" 946 (let ((data-final nil) 948 (setf data-final (take-in-turn blocks)) 950 ((or (= blk1 0) (= blk2 0)) 951 ;; only one kind of block exists 952 (setf left-blks nil)) 954 ;; block 1 has more elements left 955 (setf left-blks (mapcar #'(lambda (blk) 957 (subseq blocks 0 blk1)))) 959 ;; block 2 has more elements left 960 (setf left-blks (mapcar #'(lambda (blk) 962 (subseq blocks blk1 (+ blk1 blk2)))))) 964 (append data-final (take-in-turn left-blks)) 967 (deftype module-color () 968 ":RAW, nothing has been done to this module; :RESERVE, format info reserve module 969 :FLIGHT/:FDARK, function pattern light/dark module; :LIGHT/:DARK, data modules" 970 '(member :raw :flight :fdark :reserve :light :dark)) 972 (defun same-color-p (color1 color2) 973 "during QR symbol evaluation, :fdark & :dark are considered to be same" 975 ((:flight :light) (or (eq color2 :flight) (eq color2 :light))) 976 ((:fdark :dark) (or (eq color2 :fdark) (eq color2 :fdark))) 977 (otherwise (eq color1 color2)))) 979 (defun raw-module-p (matrix i j) 980 "nothing has been done to MATRIX[I, J]" 981 (eq (aref matrix i j) :raw)) 983 (defun make-modules-matrix (modules &optional (init :raw)) 984 "make a raw matrix with MODULES * MODULES elements" 985 (make-array `(,modules ,modules) :initial-element init)) 987 (defun make-matrix (version &optional (init :raw)) 988 "make a raw matrix according to VERSION" 989 (let ((n (matrix-modules version))) 990 (make-modules-matrix n init))) 992 (defun paint-square (matrix x y n &optional (color :fdark)) 993 "Paint a square of size N*N starting from upleft (X, Y) in MATRIX to COLOR" 994 (let ((maxx (+ x n -1)) 996 (loop for i from x to maxx do 997 (loop for j from y to maxy do 998 (setf (aref matrix i j) color)))) 1001 ;;; Function Patterns 1002 (defun function-patterns (matrix version) 1003 (let ((modules (matrix-modules version))) 1004 (finder-patterns matrix modules) 1005 (separator matrix modules) 1006 (timing-patterns matrix modules) 1007 (alignment-patterns matrix version)) 1009 ;; a) Finder Patterns: fixed position in matrix 1010 (defun one-finder-pattern (matrix x y) 1011 "Paint one finder pattern starting from upleft (X, Y)" 1012 (paint-square matrix x y 7 :fdark) 1013 (paint-square matrix (+ x 1) (+ y 1) 5 :flight) 1014 (paint-square matrix (+ x 2) (+ y 2) 3 :fdark)) 1015 (defun finder-patterns (matrix modules) 1016 ;; top-left finder pattern 1017 (one-finder-pattern matrix 0 0) 1018 ;; top-right finder pattern 1019 (one-finder-pattern matrix (- modules 7) 0) 1020 ;; bottom-left finder pattern 1021 (one-finder-pattern matrix 0 (- modules 7))) 1023 ;; b) Separator: fixed position in matrix 1024 (defun separator (matrix modules) 1026 ;; top-left horizontal separator 1027 (setf (aref matrix 7 j) :flight) 1028 ;; top-right horizontal separator 1029 (setf (aref matrix 7 (- modules j 1)) :flight) 1030 ;; bottom-left horizontal separator 1031 (setf (aref matrix (- modules 8) j) :flight)) 1033 ;; top-left vertical separator 1034 (setf (aref matrix i 7) :flight) 1035 ;; bottom-left vertical separator 1036 (setf (aref matrix (- modules i 1) 7) :flight) 1037 ;; top-right vertical separator 1038 (setf (aref matrix i (- modules 8)) :flight)) 1041 ;; c) Timing patterns 1042 (defun timing-patterns (matrix modules) 1043 (let ((color :fdark)) 1044 (loop for idx from 8 to (- modules 9) do 1047 (setf color :flight)) 1049 (setf (aref matrix 6 idx) color) 1051 (setf (aref matrix idx 6) color))) 1054 ;; d) Alignment Patterns: varies between versions 1055 ;; may overlap timing patterns, modules coincide with that of timing patterns 1056 (defun one-align-pattern (matrix x y) 1057 "Paint one alignment pattern centered at (X, Y)" 1058 (paint-square matrix (- x 2) (- y 2) 5 :fdark) 1059 (paint-square matrix (- x 1) (- y 1) 3 :flight) 1060 (paint-square matrix x y 1 :fdark)) 1061 (defun alignment-patterns (matrix version) 1062 (dolist (center (align-centers version) matrix) 1063 (one-align-pattern matrix (first center) (second center)))) 1066 (defun symbol-character (bstream matrix version) 1067 (let ((modules (matrix-modules version))) 1068 (reserve-information matrix version) 1069 (bstream-placement bstream matrix modules)) 1071 ;; reserve format information & version information 1072 (defun reserve-information (matrix version) 1073 (let ((modules (matrix-modules version))) 1074 ;; format information... 1075 ;; top-left & top-right horizontal 1077 (when (raw-module-p matrix 8 j) 1078 (setf (aref matrix 8 j) :reserve)) 1079 (setf (aref matrix 8 (- modules j 1)) :reserve)) 1080 (setf (aref matrix 8 8) :reserve) 1081 ;; top-left & bottom-left vertical 1083 (when (raw-module-p matrix i 8) 1084 (setf (aref matrix i 8) :reserve)) 1085 (setf (aref matrix (- modules i 1) 8) :reserve)) 1087 (setf (aref matrix (- modules 8) 8) :fdark) 1089 ;; version information for version 7-40 1090 (when (>= version 7) 1091 (version-information matrix modules version)))) 1093 (defun paint-fcolor-bit (matrix i j bit) 1094 "Paint function pattern color for MATRIX[I, J] according to BIT of {0, 1}" 1095 (setf (aref matrix i j) (case bit 1096 (0 :flight) (1 :fdark)))) 1097 (defun version-information (matrix modules version) 1098 "version information placement on two blocks of modules: 1099 bottom-left 3*6 block: [modules-11, modules-9] * [0, 5] 1100 top-right 6*3 block: [0, 5] * [modules-11, modules-9]" 1101 (assert (>= version 7)) 1102 (let ((vib (version-ecc version)) 1104 (start (- modules 9)) 1105 (bound (- modules 11)) 1107 (dolist (bit vib matrix) 1108 (paint-fcolor-bit matrix i j bit) 1109 (paint-fcolor-bit matrix j i bit) 1110 (if (>= (- i 1) bound) 1116 ;; Symbol character placement 1117 (defun paint-color-bit (matrix i j bit) 1118 "Paint data color for MATRIX[I, J] according to BIT of {0, 1}" 1119 (setf (aref matrix i j) (case bit 1120 (0 :light) (1 :dark)))) 1121 (defun bstream-placement (bstream matrix modules) 1122 "2X4 module block for a regular symbol character. Regard the interleaved 1123 codeword sequence as a single bit stream, which is placed in the two module 1124 wide columns, alternately in the right and left modules, moving upwards or 1125 downwards according to DIRECTION, skipping function patterns, changing DIRECTION 1126 at the top or bottom of the symbol. The only exception is that no block should 1127 ever overlap the vertical timing pattern." 1128 (let ((i (- modules 1)) 1130 ;; -1: upwards, +1: downwards 1132 (len (length bstream))) 1134 ((>= idx len) matrix) 1135 (when (raw-module-p matrix i j) 1136 (paint-color-bit matrix i j (nth idx bstream)) 1138 (when (and (>= (- j 1) 0) 1139 (raw-module-p matrix i (- j 1))) 1141 (paint-color-bit matrix i (- j 1) (nth idx bstream)) 1143 (if (< -1 (+ i direction) modules) 1146 ;; reverse direction 1147 (setf direction (- direction)) 1149 ;; vertical timing pattern reached, the next block starts 1150 ;; to the left of it 1154 ;;; format information, during and after masking 1155 (defun format-information (matrix modules level mask-ind) 1156 ;; format information bistream 1157 (let ((fib (format-ecc level mask-ind)) 1161 (setf darks (count-if #'(lambda (elem) (= elem 1)) fib)) 1162 ;; horizontal 14 ~ 8 1163 (loop for j from 0 to 7 do 1164 (when (eq (aref matrix 8 j) :reserve) 1165 (paint-fcolor-bit matrix 8 j (nth idx fib)) 1168 (loop for i from (- modules 1) downto (- modules 7) do 1169 (paint-fcolor-bit matrix i 8 (nth idx2 fib)) 1172 (loop for j from (- modules 8) to (- modules 1) do 1173 (paint-fcolor-bit matrix 8 j (nth idx fib)) 1176 (loop for i from 8 downto 0 do 1177 (when (eq (aref matrix i 8) :reserve) 1178 (paint-fcolor-bit matrix i 8 (nth idx2 fib)) 1180 (values matrix darks))) 1182 ;;; only encoding region modules (excluding format information) are masked 1183 (defun encoding-module-p (matrix i j) 1184 "modules belong to encoding region, excluding format & version information" 1185 (or (eq (aref matrix i j) :light) 1186 (eq (aref matrix i j) :dark))) 1187 (defun non-mask-module-p (matrix i j) 1188 (not (encoding-module-p matrix i j))) 1189 (defun reverse-module-color (matrix i j) 1190 (case (aref matrix i j) 1191 (:dark :light) (:light :dark))) 1193 ;;; all modules are evaluated: 1194 ;;; there should be only :dark :light :fdark :flight modules left by now 1195 (defun dark-module-p (matrix i j) 1196 (or (eq (aref matrix i j) :fdark) 1197 (eq (aref matrix i j) :dark))) 1199 (defun copy-and-mask (matrix modules level mask-ind) 1200 "make a new matrix and mask using MASK-IND for later evaluation" 1201 (let ((ret (make-modules-matrix modules)) 1202 (mask-p (mask-condition mask-ind)) 1204 (dotimes (i modules) 1205 (dotimes (j modules) 1207 ((non-mask-module-p matrix i j) 1208 (setf (aref ret i j) (aref matrix i j))) 1209 ((funcall mask-p i j) ; need mask 1210 (setf (aref ret i j) (reverse-module-color matrix i j))) 1212 (setf (aref ret i j) (aref matrix i j)))) 1213 (when (dark-module-p ret i j) 1215 (multiple-value-bind (dummy fi-darks) 1216 (format-information ret modules level mask-ind) 1217 (declare (ignore dummy)) 1218 ;; add format information dark modules 1219 (values ret (+ darks fi-darks))))) 1221 (defun mask-matrix (matrix modules level mask-ind) 1222 "do not evaluate, just go ahead and mask MATRIX using MASK-IND mask pattern" 1223 (let ((mask-p (mask-condition mask-ind))) 1224 (dotimes (i modules) 1225 (dotimes (j modules) 1226 (and (encoding-module-p matrix i j) 1227 (funcall mask-p i j) 1228 (setf (aref matrix i j) (reverse-module-color matrix i j))))) 1229 ;; paint format information 1230 (format-information matrix modules level mask-ind) 1233 (defun choose-masking (matrix modules level) 1234 "mask and evaluate using each mask pattern, choose the best mask result" 1237 (mask-indicator nil) 1239 (square (* modules modules)) 1241 (dotimes (i *mask-pattern-num*) 1242 (multiple-value-bind (cur-matrix darks) 1243 (copy-and-mask matrix modules level i) 1244 ;; feature 4: proportion of dark modules in entire symbol 1245 (let ((bratio (/ (+ (* darks 200) square) square 2))) 1246 (setf cur-penalty (* (/ (abs (- bratio 50)) 5) n4))) 1247 (incf cur-penalty (evaluate-feature-123 cur-matrix modules)) 1248 (when (or (null min-penalty) 1249 (< cur-penalty min-penalty)) 1250 (setf min-penalty cur-penalty 1252 best-matrix cur-matrix)))) 1253 (values best-matrix mask-indicator))) 1255 ;;; feature 1 & 2 & 3 1256 (defun evaluate-feature-123 (matrix modules) 1258 (incf penalty (evaluate-feature-2 matrix modules)) 1259 (dotimes (col modules) 1260 (let ((rlength (calc-run-length matrix modules col))) 1261 (incf penalty (evaluate-feature-1 rlength)) 1262 (incf penalty (evaluate-feature-3 rlength)))) 1263 (dotimes (row modules) 1264 (let ((rlength (calc-run-length matrix modules row :col))) 1265 (incf penalty (evaluate-feature-1 rlength)) 1266 (incf penalty (evaluate-feature-3 rlength)))) 1269 (defun calc-run-length (matrix modules num &optional (direction :row)) 1270 "list of number of adjacent modules in same color" 1273 (labels ((get-elem (idx) 1275 (:row (aref matrix num idx)) 1276 (:col (aref matrix idx num)))) 1277 (add-to-list (list elem) 1278 (append list (list elem)))) 1279 ;; we make sure (NTH 1 rlength) is for dark module 1280 (when (same-color-p (get-elem 0) :dark) 1281 (setf rlength (add-to-list rlength -1) 1283 (setf rlength (add-to-list rlength 1)) 1285 (loop for i from 1 to (- modules 1) do 1286 (if (same-color-p (get-elem i) (get-elem (- i 1))) 1287 (incf (nth ridx rlength)) 1290 (setf rlength (add-to-list rlength 1))))) 1293 (defun evaluate-feature-1 (rlength) 1294 "(5 + i) adjacent modules in row/column in same color. (N1 + i) points, N1 = 3" 1297 (dolist (sz rlength penalty) 1299 (incf penalty (+ n1 sz -5)))))) 1301 (defun evaluate-feature-3 (rlength) 1302 "1:1:3:1:1 ration (dark:light:dark:light:dark) pattern in row/column, 1303 preceded or followed by light area 4 modules wide. N3 points, N3 = 40" 1305 (len (length rlength)) 1308 ((>= i (- len 2)) penalty) 1309 (when (and (= (mod i 2) 1) ; for dark module 1310 (= (mod (nth i rlength) 3) 0) 1311 (let ((fact (floor (nth i rlength) 3))) 1314 (nth (- i 2) rlength) 1315 (nth (- i 1) rlength) 1316 (nth (+ i 1) rlength) 1317 (nth (+ i 2) rlength)) 1319 ((<= (- i 3) 0) (incf penalty n3)) 1320 ((>= (+ i 4) len) (incf penalty n3)) 1321 ((>= (nth (- i 3) rlength) (* 4 fact)) (incf penalty n3)) 1322 ((>= (nth (+ i 3) rlength) (* 4 fact)) (incf penalty n3)))))))))) 1324 (defun evaluate-feature-2 (matrix modules) 1325 "block m * n of modules in same color. N2 * (m-1) * (n-1) points, N2=3" 1329 (dotimes (i (- modules 1) penalty) 1330 (dotimes (j (- modules 1)) 1331 (when (dark-module-p matrix i j) 1333 (when (dark-module-p matrix (+ i 1) j) 1335 (when (dark-module-p matrix i (+ j 1)) 1337 (when (dark-module-p matrix (+ i 1) (+ j 1)) 1339 (when (or (= bcount 0) (= bcount 4)) 1340 (incf penalty n2)))))) 1342 (defclass qr-symbol () 1343 ((matrix :initform nil :initarg :matrix :reader matrix 1344 :documentation "qr code symbol as matrix") 1345 (modules :initform nil :initarg :modules :reader modules 1346 :documentation "qr code symbol modules"))) 1348 (defmethod print-object ((symbol qr-symbol) stream) 1350 (with-slots (matrix modules) symbol 1351 (format stream "qr symbol ~A x ~A:~%" modules modules) 1352 (dotimes (i modules) 1353 (dotimes (j modules) 1354 (if (dark-module-p matrix i j) 1355 (format stream "1 ") 1356 (format stream "0 "))) 1357 (format stream "~%")))) 1359 ;;; FIXME: other encodings??? 1360 (defun ascii->bytes (text) 1361 (map 'list #'char-code text)) 1363 (defun bytes->input (bytes version level mode) 1364 (setf version (min (max version 1) 40)) 1365 (let ((input (make-instance 'qr-input :bytes bytes :version version 1366 :ec-level level :mode mode))) 1367 (data-encoding input) 1369 (structure-message input) 1370 (module-placement input) 1373 (defun input->symbol (input) 1374 "encode qr symbol from a qr-input" 1375 (multiple-value-bind (matrix mask-ref) 1376 (data-masking input) 1377 (declare (ignore mask-ref)) 1378 (let ((modules (matrix-modules (version input)))) 1379 (make-instance 'qr-symbol :matrix matrix :modules modules)))) 1381 (defun encode-symbol-bytes (bytes &key (version 1) (level :level-m) (mode nil)) 1382 "encode final qr symbol from BYTES list" 1383 (let ((input (bytes->input bytes version level mode))) 1384 (log:debug! (format nil "version: ~A; segments: ~A~%" (version input) 1386 (input->symbol input))) 1388 ;;;----------------------------------------------------------------------------- 1389 ;;; One Ring to Rule Them All, One Ring to Find Them, 1390 ;;; One Ring to Bring Them All and In the Darkness Blind Them: 1391 ;;; This function wraps all we need. 1392 ;;;----------------------------------------------------------------------------- 1393 ;; (sdebug :dbg-input) 1394 (defun encode-symbol (text &key (version 1) (level :level-m) (mode nil)) 1395 "encode final qr symbol, unless you know what you are doing, leave MODE NIL" 1396 (let ((bytes (ascii->bytes text))) 1397 (encode-symbol-bytes bytes :version version :level level :mode mode))) 1399 ;;; Table 1 - Codeword capacity of all versions of QR Code 2005 1400 ;;; excluding Micro QR Code, varies between version 1401 (defvar *codeword-capacity-table* 1402 #2A((-1 -1 -1 -1 -1 -1) ; 0, no such version 1403 (21 202 31 208 26 0) (25 235 31 359 44 7) 1404 (29 243 31 567 70 7) (33 251 31 807 100 7) 1405 (37 259 31 1079 134 7) (41 267 31 1383 172 7) 1406 (45 390 67 1568 196 0) (49 398 67 1936 242 0) 1407 (53 406 67 2336 292 0) (57 414 67 2768 346 0) ; Version 10 1408 (61 422 67 3232 404 0) (65 430 67 3728 466 0) 1409 (69 438 67 4256 532 0) (73 611 67 4651 581 3) 1410 (77 619 67 5243 655 3) (81 627 67 5867 733 3) 1411 (85 635 67 6523 815 3) (89 643 67 7211 901 3) 1412 (93 651 67 7931 991 3) (97 659 67 8683 1085 3) ; Version 20 1413 (101 882 67 9252 1156 4) (105 890 67 10068 1258 4) 1414 (109 898 67 10916 1364 4) (113 906 67 11796 1474 4) 1415 (117 914 67 12708 1588 4) (121 922 67 13652 1706 4) 1416 (125 930 67 14628 1828 4) (129 1203 67 15371 1921 3) 1417 (133 1211 67 16411 2051 3) (137 1219 67 17483 2185 3) ; Version 30 1418 (141 1227 67 18587 2323 3) (145 1235 67 19723 2465 3) 1419 (149 1243 67 20891 2611 3) (153 1251 67 22091 2761 3) 1420 (157 1574 67 23008 2876 0) (161 1582 67 24272 3034 0) 1421 (165 1590 67 25568 3196 0) (169 1598 67 26896 3362 0) 1422 (173 1606 67 28256 3532 0) (177 1614 67 29648 3706 0)) ; Version 40 1423 "Number of modules (as version increases, 4 modules added) A | Function pattern 1424 modules B | Format and Version information modules C | Data modules (A^2-B-C) | 1425 Data capacity codewords (bytes, including ecc codewords) | Remainder bits.") 1426 (defun codeword-capacity (version) 1427 "codeword: data word + ecc word" 1428 (aref *codeword-capacity-table* version 4)) 1429 (defun matrix-modules (version) 1430 (aref *codeword-capacity-table* version 0)) 1431 (defun remainder-bits (version) 1432 (aref *codeword-capacity-table* version 5)) 1434 (defun mode->index (mode) 1441 (deftype ecc-level () 1442 '(member :level-l :level-m :level-q :level-h)) 1443 (defun level->index (level) 1450 ;;; (Part I of) Table 9 - Number of Error Correction Codewords (bytes) 1451 ;;; varies between version and level 1452 (defvar *ecc-codewords-table* 1453 ;; (:level-l :level-m :level-q :level-h) 1454 #2A((-1 -1 -1 -1) ;; 0, no such version 1455 (7 10 13 17) (10 16 22 28) (15 26 36 44) 1456 (20 36 52 64) (26 48 72 88) (36 64 96 112) 1457 (40 72 108 130) (48 88 132 156) (60 110 160 192) 1458 (72 130 192 224) (80 150 224 264) (96 176 260 308) 1459 (104 198 288 352) (120 216 320 384) (132 240 360 432) 1460 (144 280 408 480) (168 308 448 532) (180 338 504 588) 1461 (196 364 546 650) (224 416 600 700) (224 442 644 750) 1462 (252 476 690 816) (270 504 750 900) (300 560 810 960) 1463 (312 588 870 1050) (336 644 952 1110) (360 700 1020 1200) 1464 (390 728 1050 1260) (420 784 1140 1350) (450 812 1200 1440) 1465 (480 868 1290 1530) (510 924 1350 1620) (540 980 1440 1710) 1466 (570 1036 1530 1800) (570 1064 1590 1890) (600 1120 1680 1980) 1467 (630 1204 1770 2100) (660 1260 1860 2220) (720 1316 1950 2310) 1468 (750 1372 2040 2430))) ;; version 1 ~ 40 1469 (defun ecc-words-capacity (version level) 1470 (aref *ecc-codewords-table* version (level->index level))) 1471 (defun data-words-capacity (version level) 1472 (- (codeword-capacity version) (ecc-words-capacity version level))) 1474 ;;; (Part II of) Table 9 - Error Correction blocks 1475 ;;; varies between version and level 1476 (defvar *ecc-blocks* 1477 ;; (version, level) => 1478 ;; (# of ec codewords for each blk, # of blk 1, # of data words for blk 1, 1479 ;; # of blk 2, # of data words for blk 2) 1480 ;; :level-l :level-m :level-q :level-h 1481 #3A(((0 0 0 0 0) (0 0 0 0 0) (0 0 0 0 0) (0 0 0 0 0)) ; no such version 1482 ((7 1 19 0 0) (10 1 16 0 0) (13 1 13 0 0) (17 1 9 0 0)) ; Version 1 1483 ((10 1 34 0 0) (16 1 28 0 0) (22 1 22 0 0) (28 1 16 0 0)) 1484 ((15 1 55 0 0) (26 1 44 0 0) (18 2 17 0 0) (22 2 13 0 0)) 1485 ((20 1 80 0 0) (18 2 32 0 0) (26 2 24 0 0) (16 4 9 0 0)) 1486 ((26 1 108 0 0) (24 2 43 0 0) (18 2 15 2 16) (22 2 11 2 12)) ; Version 5 1487 ((18 2 68 0 0) (16 4 27 0 0) (24 4 19 0 0) (28 4 15 0 0)) 1488 ((20 2 78 0 0) (18 4 31 0 0) (18 2 14 4 15) (26 4 13 1 14)) 1489 ((24 2 97 0 0) (22 2 38 2 39) (22 4 18 2 19) (26 4 14 2 15)) 1490 ((30 2 116 0 0) (22 3 36 2 37) (20 4 16 4 17) (24 4 12 4 13)) 1491 ((18 2 68 2 69) (26 4 43 1 44) (24 6 19 2 20) (28 6 15 2 16)) ; Version 10 1492 ((20 4 81 0 0) (30 1 50 4 51) (28 4 22 4 23) (24 3 12 8 13)) 1493 ((24 2 92 2 93) (22 6 36 2 37) (26 4 20 6 21) (28 7 14 4 15)) 1494 ((26 4 107 0 0) (22 8 37 1 38) (24 8 20 4 21) (22 12 11 4 12)) 1495 ((30 3 115 1 116) (24 4 40 5 41) (20 11 16 5 17) (24 11 12 5 13)) 1496 ((22 5 87 1 88) (24 5 41 5 42) (30 5 24 7 25) (24 11 12 7 13)) ; Version 15 1497 ((24 5 98 1 99) (28 7 45 3 46) (24 15 19 2 20) (30 3 15 13 16)) 1498 ((28 1 107 5 108) (28 10 46 1 47) (28 1 22 15 23) (28 2 14 17 15)) 1499 ((30 5 120 1 121) (26 9 43 4 44) (28 17 22 1 23) (28 2 14 19 15)) 1500 ((28 3 113 4 114) (26 3 44 11 45) (26 17 21 4 22) (26 9 13 16 14)) 1501 ((28 3 107 5 108) (26 3 41 13 42) (30 15 24 5 25) (28 15 15 10 16)) ; Version 20 1502 ((28 4 116 4 117) (26 17 42 0 0) (28 17 22 6 23) (30 19 16 6 17)) 1503 ((28 2 111 7 112) (28 17 46 0 0) (30 7 24 16 25) (24 34 13 0 0)) 1504 ((30 4 121 5 122) (28 4 47 14 48) (30 11 24 14 25) (30 16 15 14 16)) 1505 ((30 6 117 4 118) (28 6 45 14 46) (30 11 24 16 25) (30 30 16 2 17)) 1506 ((26 8 106 4 107) (28 8 47 13 48) (30 7 24 22 25) (30 22 15 13 16)) ; Version 25 1507 ((28 10 114 2 115) (28 19 46 4 47) (28 28 22 6 23) (30 33 16 4 17)) 1508 ((30 8 122 4 123) (28 22 45 3 46) (30 8 23 26 24) (30 12 15 28 16)) 1509 ((30 3 117 10 118) (28 3 45 23 46) (30 4 24 31 25) (30 11 15 31 16)) 1510 ((30 7 116 7 117) (28 21 45 7 46) (30 1 23 37 24) (30 19 15 26 16)) 1511 ((30 5 115 10 116) (28 19 47 10 48) (30 15 24 25 25) (30 23 15 25 16)) ; Version 30 1512 ((30 13 115 3 116) (28 2 46 29 47) (30 42 24 1 25) (30 23 15 28 16)) 1513 ((30 17 115 0 0) (28 10 46 23 47) (30 10 24 35 25) (30 19 15 35 16)) 1514 ((30 17 115 1 116) (28 14 46 21 47) (30 29 24 19 25) (30 11 15 46 16)) 1515 ((30 13 115 6 116) (28 14 46 23 47) (30 44 24 7 25) (30 59 16 1 17)) 1516 ((30 12 121 7 122) (28 12 47 26 48) (30 39 24 14 25) (30 22 15 41 16)) ; Version 35 1517 ((30 6 121 14 122) (28 6 47 34 48) (30 46 24 10 25) (30 2 15 64 16)) 1518 ((30 17 122 4 123) (28 29 46 14 47) (30 49 24 10 25) (30 24 15 46 16)) 1519 ((30 4 122 18 123) (28 13 46 32 47) (30 48 24 14 25) (30 42 15 32 16)) 1520 ((30 20 117 4 118) (28 40 47 7 48) (30 43 24 22 25) (30 10 15 67 16)) 1521 ((30 19 118 6 119) (28 18 47 31 48) (30 34 24 34 25) (30 20 15 61 16)) ; Version 40 1523 (defun ecc-block-nums (version level) 1524 "# of ec codewords for each blk, # of blk 1, # of data words for blk 1, ..." 1525 (let ((lidx (level->index level))) 1526 (values (aref *ecc-blocks* version lidx 0) 1527 (aref *ecc-blocks* version lidx 1) 1528 (aref *ecc-blocks* version lidx 2) 1529 (aref *ecc-blocks* version lidx 3) 1530 (aref *ecc-blocks* version lidx 4)))) 1532 (defun minimum-version (init-version nbytes level) 1533 "minimum version that can hold NBYTES data words, or INIT-VERSION if bigger" 1534 (do ((v init-version (1+ v))) 1536 (when (>= (data-words-capacity v level) nbytes) 1537 (return-from minimum-version v)))) 1539 (defun version-range (version) 1541 ((<= 1 version 9) 0) 1542 ((<= 10 version 26) 1) 1543 ((<= 27 version 40) 2))) 1545 ;;; Table 3 - Number of bits in character count indicator for QR Code 2005 1546 (defvar *char-count-indicator* 1547 ;; :numeric :alnum :byte :kanji 1548 #2A((10 9 8 8) ; version-range 0 1549 (12 11 16 10) ; version-range 1 1550 (14 13 16 12))) ; version-range 2 1551 (defun char-count-bits (version mode) 1552 (let ((i (version-range version)) 1553 (j (mode->index mode))) 1554 (aref *char-count-indicator* i j))) 1556 ;;; Table E.1 - Row/column coordinates of center modules of alignment patterns 1557 ;;; varies between versions 1558 (defvar *align-coord-table* 1559 #2A((0 ()) ; 0, no such version 1560 (0 ()) (1 (6 18)) (1 (6 22)) 1561 (1 (6 26)) (1 (6 30)) (1 (6 34)) 1562 (6 (6 22 38)) (6 (6 24 42)) (6 (6 26 46)) 1563 (6 (6 28 50)) (6 (6 30 54)) (6 (6 32 58)) 1564 (6 (6 34 62)) (13 (6 26 46 66)) (13 (6 26 48 70)) 1565 (13 (6 26 50 74)) (13 (6 30 54 78)) (13 (6 30 56 82)) 1566 (13 (6 30 58 86)) (13 (6 34 62 90)) (22 (6 28 50 72 94)) 1567 (22 (6 26 50 74 98)) (22 (6 30 54 78 102)) (22 (6 28 54 80 106)) 1568 (22 (6 32 58 84 110)) (22 (6 30 58 86 114)) (22 (6 34 62 90 118)) 1569 (33 (6 26 50 74 98 122)) (33 (6 30 54 78 102 126)) (33 (6 26 52 78 104 130)) 1570 (33 (6 30 56 82 108 134)) (33 (6 34 60 86 112 138)) (33 (6 30 58 86 114 142)) 1571 (33 (6 34 62 90 118 146)) (46 (6 30 54 78 102 126 150)) (46 (6 24 50 76 102 128 154)) 1572 (46 (6 28 54 80 106 132 158)) (46 (6 32 58 84 110 136 162)) (46 (6 26 54 82 110 138 166)) 1573 (46 (6 30 58 86 114 142 170))) 1574 "# of Alignment Patterns, row/column coordinates of center modules.") 1575 (defun valid-center-p (x y modules) 1576 "The alignment center module is not in Finder Patterns." 1577 (not (or (and (<= 0 x 8) (<= 0 y 8)) ; upleft finder pattern 1579 (<= (- modules 8) y (- modules 1))) ; upright finder pattern 1580 (and (<= (- modules 8) x (- modules 1)) 1582 (defun align-centers (version) 1583 "list of all valid alignment pattern center modules under VERSION" 1584 (let* ((modules (matrix-modules version)) 1585 (coords (aref *align-coord-table* version 1)) 1586 (len (length coords)) 1589 (loop for j from i to (- len 1) do 1590 (let ((x (nth i coords)) 1592 (when (valid-center-p x y modules) 1593 (push (list x y) centers)) 1595 (when (valid-center-p y x modules) 1596 (push (list y x) centers)))))) 1599 (defvar *mask-pattern-num* 8) 1600 (defun mask-condition (indicator) 1603 ;; (i + j) mod 2 == 0 1604 (0 (= (mod (+ i j) 2) 0)) 1609 ;; (i + j) mod 3 == 0 1610 (3 (= (mod (+ i j) 3) 0)) 1611 ;; ((i/2) + (j/3)) mod 2 == 0 1612 (4 (= (mod (+ (floor i 2) (floor j 3)) 2) 0)) 1613 ;; (i*j) mod 2 + (i*j) mod 3 == 0 1614 (5 (= (+ (mod (* i j) 2) (mod (* i j) 3)) 0)) 1615 ;; ((i*j) mod 2 + (i*j) mod 3)) mod 2 == 0 1616 (6 (= (mod (+ (mod (* i j) 2) (mod (* i j) 3)) 2) 0)) 1617 ;; ((i+j) mod 2 + (i*j) mod 3)) mod 2 == 0 1618 (7 (= (mod (+ (mod (+ i j) 2) (mod (* i j) 3)) 2) 0))))) 1620 (defvar *ecc-level-indicator* #((0 1) (0 0) (1 1) (1 0)) 1621 ":level-l :level-m :level-q :level-h") 1622 (defun level-indicator (level) 1623 (aref *ecc-level-indicator* (level->index level))) 1624 (defvar *mask-pattern-reference* 1625 #((0 0 0) (0 0 1) (0 1 0) (0 1 1) 1626 (1 0 0) (1 0 1) (1 1 0) (1 1 1))) 1627 (defun mask-pattern-ref (ind) 1628 (aref *mask-pattern-reference* ind))