├── .gitignore
├── .project
├── .settings
├── .jsdtscope
├── com.palantir.typescript.prefs
├── org.eclipse.core.resources.prefs
├── org.eclipse.jdt.core.prefs
├── org.eclipse.wst.jsdt.ui.superType.container
└── org.eclipse.wst.jsdt.ui.superType.name
├── LICENSE
├── README.md
├── as3
├── .gitignore
└── src
│ ├── as3
│ └── com
│ │ └── d_project
│ │ └── qrcode
│ │ ├── BitBuffer.as
│ │ ├── ErrorCorrectLevel.as
│ │ ├── MaskPattern.as
│ │ ├── Mode.as
│ │ ├── Polynomial.as
│ │ ├── QR8BitByte.as
│ │ ├── QRAlphaNum.as
│ │ ├── QRCode.as
│ │ ├── QRData.as
│ │ ├── QRKanji.as
│ │ ├── QRMath.as
│ │ ├── QRNumber.as
│ │ ├── QRUtil.as
│ │ ├── RSBlock.as
│ │ ├── StringUtil.as
│ │ └── mx
│ │ └── QRCode.as
│ ├── assets
│ ├── README.txt
│ └── manifest.xml
│ ├── build.xml
│ └── sample
│ ├── QRCodeSample1.as
│ └── QRCodeSample2.mxml
├── hack
├── .gitignore
├── .hhconfig
├── composer.json
├── composer.lock
├── hh_autoload.json
├── hhast-lint.json
├── hhast_lint.json
├── samples
│ ├── hhvm_generated.html
│ ├── sample.html
│ ├── sample_custom.php
│ ├── sample_html.php
│ └── sample_image.php
├── src
│ └── qrcode.hack
└── unit_test.diffme.gif
├── java
├── .gitignore
├── README.txt
├── build.gradle
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── d_project
│ │ │ └── qrcode
│ │ │ ├── BitBuffer.java
│ │ │ ├── ErrorCorrectionLevel.java
│ │ │ ├── MaskPattern.java
│ │ │ ├── Mode.java
│ │ │ ├── Polynomial.java
│ │ │ ├── QR8BitByte.java
│ │ │ ├── QRAlphaNum.java
│ │ │ ├── QRCode.java
│ │ │ ├── QRData.java
│ │ │ ├── QRKanji.java
│ │ │ ├── QRMath.java
│ │ │ ├── QRNumber.java
│ │ │ ├── QRUtil.java
│ │ │ ├── RSBlock.java
│ │ │ └── web
│ │ │ ├── GIFImage.java
│ │ │ └── QRCodeServlet.java
│ └── webapp
│ │ ├── WEB-INF
│ │ └── web.xml
│ │ ├── form.jsp
│ │ └── index.jsp
│ └── test
│ └── java
│ └── com
│ └── d_project
│ └── qrcode
│ ├── BitBufferTest.java
│ ├── PolynomialTest.java
│ ├── QRCodeTest.java
│ └── web
│ └── GIFImageTest.java
├── js
├── .gitignore
├── .npmignore
├── README.md
├── demo
│ ├── assets
│ │ ├── qrcode.png
│ │ ├── sample.js
│ │ └── style.css
│ └── index.html
├── misc
│ ├── .gitignore
│ ├── build.xml
│ └── src
│ │ ├── GenSJISSupport.java
│ │ ├── SJIS.txt
│ │ └── qrcode_SJIS.js.tmpl
├── package.json
├── qrcode.d.ts
├── qrcode.js
├── qrcode_SJIS.js
├── qrcode_UTF8.js
├── sample.html
├── sample.js
├── test
│ └── qrcode.js
└── ts-test
│ ├── .gitignore
│ ├── Gruntfile.js
│ ├── package.json
│ └── src
│ ├── .gitignore
│ └── import_test.ts
├── php
├── qrcode.php
├── sample.html
├── sample_custom.php
├── sample_html.php
└── sample_image.php
├── python
└── qrcode.py
├── ruby
└── qrcode.rb
└── ts
├── .gitignore
└── src
└── ts
├── com
└── d_project
│ ├── image
│ └── GIFImage.ts
│ ├── io
│ ├── Base64.ts
│ ├── Base64DecodeInputStream.ts
│ ├── Base64EncodeOutputStream.ts
│ ├── ByteArrayInputStream.ts
│ ├── ByteArrayOutputStream.ts
│ ├── InputStream.ts
│ └── OutputStream.ts
│ ├── qrcode
│ ├── BitBuffer.ts
│ ├── ErrorCorrectLevel.ts
│ ├── MaskPattern.ts
│ ├── Mode.ts
│ ├── Polynomial.ts
│ ├── QR8BitByte.ts
│ ├── QRAlphaNum.ts
│ ├── QRCode.ts
│ ├── QRData.ts
│ ├── QRKanji.ts
│ ├── QRMath.ts
│ ├── QRNumber.ts
│ ├── QRUtil.ts
│ └── RSBlock.ts
│ └── text
│ ├── createStringToBytes.ts
│ ├── stringToBytes_SJIS.ts
│ └── stringToBytes_UTF8.ts
├── test.html
└── test.ts
/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | qrcode-generator
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.wst.jsdt.core.javascriptValidator
10 |
11 |
12 |
13 |
14 | com.palantir.typescript.typeScriptBuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.wst.jsdt.core.jsNature
21 | com.palantir.typescript.typeScriptNature
22 |
23 |
24 |
25 | 1476438204826
26 |
27 | 26
28 |
29 | org.eclipse.ui.ide.multiFilter
30 | 1.0-name-matches-true-false-node_modules
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/.settings/.jsdtscope:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.settings/com.palantir.typescript.prefs:
--------------------------------------------------------------------------------
1 | build.path.exportedFolder=
2 | build.path.sourceFolder=
3 | compiler.codeGenTarget=ECMASCRIPT5
4 | compiler.compileOnSave=false
5 | compiler.generateDeclarationFiles=false
6 | compiler.inlineSourceMap=false
7 | compiler.inlineSources=false
8 | compiler.jsx=NONE
9 | compiler.mapSourceFiles=false
10 | compiler.moduleGenTarget=NONE
11 | compiler.moduleResolution=CLASSIC
12 | compiler.noFallthroughCasesInSwitch=false
13 | compiler.noImplicitAny=false
14 | compiler.noImplicitReturns=false
15 | compiler.noLib=false
16 | compiler.outputDirOption=
17 | compiler.outputFileOption=
18 | compiler.removeComments=false
19 | compiler.suppressExcessPropertyErrors=false
20 | compiler.suppressImplicitAnyIndexErrors=false
21 | eclipse.preferences.version=1
22 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding//php/sample_custom.php=MS932
3 | encoding//php/sample_html.php=MS932
4 | encoding//php/sample_image.php=MS932
5 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5 | org.eclipse.jdt.core.compiler.compliance=1.5
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11 | org.eclipse.jdt.core.compiler.source=1.5
12 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.jsdt.ui.superType.container:
--------------------------------------------------------------------------------
1 | org.eclipse.wst.jsdt.launching.JRE_CONTAINER
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.jsdt.ui.superType.name:
--------------------------------------------------------------------------------
1 | Global
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2009 Kazuhiko Arase
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # qrcode-generator
2 | QR Code Generator implementation in JavaScript, Java and more
3 |
4 | [online demo(js)](https://kazuhikoarase.github.io/qrcode-generator/js/demo/)
5 |
6 | All the implementations are based on JIS X 0510:1999.
7 |
8 | The word "QR Code" is registered trademark of DENSO WAVE INCORPORATED
9 |
http://www.denso-wave.com/qrcode/faqpatent-e.html
10 |
--------------------------------------------------------------------------------
/as3/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /dist
3 |
--------------------------------------------------------------------------------
/as3/src/as3/com/d_project/qrcode/BitBuffer.as:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode {
2 |
3 | /**
4 | * BitBuffer
5 | * @author Kazuhiko Arase
6 | */
7 | internal class BitBuffer {
8 |
9 | private var buffer : Array;
10 |
11 | private var length : int;
12 |
13 | public function BitBuffer() {
14 | buffer = new Array();
15 | length = 0;
16 | }
17 |
18 | public function getBuffer() : Array {
19 | return buffer;
20 | }
21 |
22 | public function getLengthInBits() : int {
23 | return length;
24 | }
25 |
26 | private function getBitAt(index : int) : Boolean {
27 | return ( (buffer[Math.floor(index / 8)] >>> (7 - index % 8) ) & 1) == 1;
28 | }
29 |
30 | public function put(num : int, length : int) : void {
31 | for (var i : int = 0; i < length; i++) {
32 | putBit( ( (num >>> (length - i - 1) ) & 1) == 1);
33 | }
34 | }
35 |
36 | public function putBit(bit : Boolean) : void {
37 |
38 | if (length == buffer.length * 8) {
39 | buffer.push(0);
40 | }
41 |
42 | if (bit) {
43 | buffer[Math.floor(length / 8)] |= (0x80 >>> (length % 8) );
44 | }
45 |
46 | length++;
47 | }
48 |
49 | public function toString() : String {
50 | var buffer : String = "";
51 | for (var i : int = 0; i < getLengthInBits(); i++) {
52 | buffer += (getBitAt(i)? '1' : '0');
53 | }
54 | return buffer;
55 | }
56 |
57 | }
58 |
59 | }
--------------------------------------------------------------------------------
/as3/src/as3/com/d_project/qrcode/ErrorCorrectLevel.as:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode {
2 |
3 | /**
4 | * 誤り訂正レベル.
5 | * @author Kazuhiko Arase
6 | */
7 | public class ErrorCorrectLevel {
8 |
9 | /**
10 | * 復元能力 7%.
11 | *
vodafoneで使用不可?
12 | */
13 | public static const L : int = 1;
14 |
15 | /**
16 | * 復元能力 15%.
17 | */
18 | public static const M : int = 0;
19 |
20 | /**
21 | * 復元能力 25%.
22 | */
23 | public static const Q : int = 3;
24 |
25 | /**
26 | * 復元能力 30%.
27 | */
28 | public static const H : int = 2;
29 |
30 | }
31 | }
--------------------------------------------------------------------------------
/as3/src/as3/com/d_project/qrcode/MaskPattern.as:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode {
2 |
3 | /**
4 | * マスクパターン.
5 | * @author Kazuhiko Arase
6 | */
7 | internal class MaskPattern {
8 |
9 | /**
10 | * マスクパターン000
11 | */
12 | public static const PATTERN000 : int = 0;
13 |
14 | /**
15 | * マスクパターン001
16 | */
17 | public static const PATTERN001 : int = 1;
18 |
19 | /**
20 | * マスクパターン010
21 | */
22 | public static const PATTERN010 : int = 2;
23 |
24 | /**
25 | * マスクパターン011
26 | */
27 | public static const PATTERN011 : int = 3;
28 |
29 | /**
30 | * マスクパターン100
31 | */
32 | public static const PATTERN100 : int = 4;
33 |
34 | /**
35 | * マスクパターン101
36 | */
37 | public static const PATTERN101 : int = 5;
38 |
39 | /**
40 | * マスクパターン110
41 | */
42 | public static const PATTERN110 : int = 6;
43 |
44 | /**
45 | * マスクパターン111
46 | */
47 | public static const PATTERN111 : int = 7;
48 |
49 | }
50 |
51 |
52 | }
--------------------------------------------------------------------------------
/as3/src/as3/com/d_project/qrcode/Mode.as:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode {
2 |
3 | /**
4 | * モード.
5 | * @author Kazuhiko Arase
6 | */
7 | public class Mode {
8 |
9 | /**
10 | * 自動モード
11 | */
12 | public static const MODE_AUTO : int = 0;
13 |
14 | /**
15 | * 数値モード
16 | */
17 | public static const MODE_NUMBER : int = 1 << 0;
18 |
19 | /**
20 | * 英数字モード
21 | */
22 | public static const MODE_ALPHA_NUM : int = 1 << 1;
23 |
24 | /**
25 | * 8ビットバイトモード
26 | */
27 | public static const MODE_8BIT_BYTE : int = 1 << 2;
28 |
29 | /**
30 | * 漢字モード
31 | */
32 | public static const MODE_KANJI : int = 1 << 3;
33 |
34 | }
35 | }
--------------------------------------------------------------------------------
/as3/src/as3/com/d_project/qrcode/Polynomial.as:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode {
2 |
3 | /**
4 | * Polynomial
5 | * @author Kazuhiko Arase
6 | */
7 | internal class Polynomial {
8 |
9 | private var num : Array;
10 |
11 | public function Polynomial(num : Array, shift : int = 0) {
12 |
13 | var offset : int = 0;
14 |
15 | while (offset < num.length && num[offset] == 0) {
16 | offset++;
17 | }
18 |
19 | this.num = new Array(num.length - offset + shift);
20 | for (var i : int = 0; i < num.length - offset; i++) {
21 | this.num[i] = num[offset + i];
22 | }
23 | }
24 |
25 | public function getAt(index : int) : int {
26 | return num[index];
27 | }
28 |
29 | public function getLength() : int {
30 | return num.length;
31 | }
32 |
33 | public function toString() : String {
34 |
35 | var buffer : String = "";
36 |
37 | for (var i : int = 0; i < getLength(); i++) {
38 | if (i > 0) {
39 | buffer += ",";
40 | }
41 | buffer += getAt(i);
42 | }
43 |
44 | return buffer;
45 | }
46 |
47 | public function toLogString() : String {
48 |
49 | var buffer : String = "";
50 |
51 | for (var i : int = 0; i < getLength(); i++) {
52 | if (i > 0) {
53 | buffer += ",";
54 | }
55 | buffer += QRMath.glog(getAt(i) );
56 |
57 | }
58 |
59 | return buffer.toString();
60 | }
61 |
62 | public function multiply(e : Polynomial) : Polynomial {
63 |
64 | var num : Array = new Array(getLength() + e.getLength() - 1);
65 |
66 | for (var i : int = 0; i < getLength(); i++) {
67 | for (var j : int = 0; j < e.getLength(); j++) {
68 | num[i + j] ^= QRMath.gexp(QRMath.glog(getAt(i) ) + QRMath.glog(e.getAt(j) ) );
69 | }
70 | }
71 |
72 | return new Polynomial(num);
73 | }
74 |
75 | public function mod(e : Polynomial) : Polynomial {
76 |
77 | if (getLength() - e.getLength() < 0) {
78 | return this;
79 | }
80 |
81 | // 最上位桁の比率
82 | var ratio : int = QRMath.glog(getAt(0) ) - QRMath.glog(e.getAt(0) );
83 |
84 | var i : int;
85 |
86 | // コピー作成
87 | var num : Array = new Array(getLength() );
88 | for (i = 0; i < getLength(); i++) {
89 | num[i] = getAt(i);
90 | }
91 |
92 | // 引き算して余りを計算
93 | for (i = 0; i < e.getLength(); i++) {
94 | num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i) ) + ratio);
95 | }
96 |
97 | // 再帰計算
98 | return new Polynomial(num).mod(e);
99 | }
100 |
101 | }
102 |
103 | }
--------------------------------------------------------------------------------
/as3/src/as3/com/d_project/qrcode/QR8BitByte.as:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode {
2 |
3 | import flash.utils.ByteArray;
4 |
5 | /**
6 | * QR8BitByte
7 | * @author Kazuhiko Arase
8 | */
9 | internal class QR8BitByte extends QRData {
10 |
11 | public function QR8BitByte(data : String) {
12 | super(Mode.MODE_8BIT_BYTE, data);
13 | }
14 |
15 | public override function write(buffer : BitBuffer) : void {
16 | var data : ByteArray = StringUtil.getBytes(getData(), QRUtil.getJISEncoding() );
17 | for (var i : int = 0; i < data.length; i++) {
18 | buffer.put(data[i], 8);
19 | }
20 | }
21 |
22 | public override function getLength() : int {
23 | return StringUtil.getBytes(getData(), QRUtil.getJISEncoding() ).length;
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/as3/src/as3/com/d_project/qrcode/QRAlphaNum.as:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode {
2 |
3 | /**
4 | * QRAlphaNum
5 | * @author Kazuhiko Arase
6 | */
7 | internal class QRAlphaNum extends QRData {
8 |
9 | public function QRAlphaNum(data : String) {
10 | super(Mode.MODE_ALPHA_NUM, data);
11 | }
12 |
13 | public override function write(buffer : BitBuffer) : void {
14 |
15 | var i : int = 0;
16 | var s : String = getData();
17 |
18 | while (i + 1 < s.length) {
19 | buffer.put(getCode(s.charAt(i) ) * 45 + getCode(s.charAt(i + 1) ), 11);
20 | i += 2;
21 | }
22 |
23 | if (i < s.length) {
24 | buffer.put(getCode(s.charAt(i) ), 6);
25 | }
26 | }
27 |
28 | public override function getLength() : int {
29 | return getData().length;
30 | }
31 |
32 | private static function getCode(c : String) : int {
33 | var code : int = c.charCodeAt(0);
34 | if (getCharCode('0') <= code && code <= getCharCode('9') ) {
35 | return code - getCharCode('0');
36 | } else if (getCharCode('A') <= code && code <= getCharCode('Z') ) {
37 | return code - getCharCode('A') + 10;
38 | } else {
39 | switch (c) {
40 | case ' ' : return 36;
41 | case '$' : return 37;
42 | case '%' : return 38;
43 | case '*' : return 39;
44 | case '+' : return 40;
45 | case '-' : return 41;
46 | case '.' : return 42;
47 | case '/' : return 43;
48 | case ':' : return 44;
49 | default :
50 | throw new Error("illegal char :" + c);
51 | }
52 | }
53 | throw new Error();
54 | }
55 |
56 | private static function getCharCode(c : String) : int {
57 | return c.charCodeAt(0);
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/as3/src/as3/com/d_project/qrcode/QRData.as:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode {
2 |
3 | /**
4 | * QRData
5 | * @author Kazuhiko Arase
6 | */
7 | internal class QRData {
8 |
9 | private var mode : int;
10 |
11 | private var data : String;
12 |
13 | public function QRData(mode : int, data : String) {
14 | this.mode = mode;
15 | this.data = data;
16 | }
17 |
18 | public function getMode() : int {
19 | return mode;
20 | }
21 |
22 | public function getData() : String {
23 | return data;
24 | }
25 |
26 | public function getLength() : int {
27 | throw new Error("not implemented.");
28 | }
29 |
30 | public function write(buffer : BitBuffer) : void {
31 | throw new Error("not implemented.");
32 | }
33 |
34 | /**
35 | * 型番及びモードに対するビット長を取得する。
36 | */
37 | public function getLengthInBits(type : int) : int {
38 |
39 | if (1 <= type && type < 10) {
40 |
41 | // 1 - 9
42 |
43 | switch(mode) {
44 | case Mode.MODE_NUMBER : return 10;
45 | case Mode.MODE_ALPHA_NUM : return 9;
46 | case Mode.MODE_8BIT_BYTE : return 8;
47 | case Mode.MODE_KANJI : return 8;
48 | default :
49 | throw new Error("mode:" + mode);
50 | }
51 |
52 | } else if (type < 27) {
53 |
54 | // 10 - 26
55 |
56 | switch(mode) {
57 | case Mode.MODE_NUMBER : return 12;
58 | case Mode.MODE_ALPHA_NUM : return 11;
59 | case Mode.MODE_8BIT_BYTE : return 16;
60 | case Mode.MODE_KANJI : return 10;
61 | default :
62 | throw new Error("mode:" + mode);
63 | }
64 |
65 | } else if (type < 41) {
66 |
67 | // 27 - 40
68 |
69 | switch(mode) {
70 | case Mode.MODE_NUMBER : return 14;
71 | case Mode.MODE_ALPHA_NUM : return 13;
72 | case Mode.MODE_8BIT_BYTE : return 16;
73 | case Mode.MODE_KANJI : return 12;
74 | default :
75 | throw new Error("mode:" + mode);
76 | }
77 |
78 | } else {
79 | throw new Error("type:" + type);
80 | }
81 | }
82 |
83 | }
84 |
85 | }
--------------------------------------------------------------------------------
/as3/src/as3/com/d_project/qrcode/QRKanji.as:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode {
2 |
3 | import flash.utils.ByteArray;
4 |
5 | /**
6 | * QRKanji
7 | * @author Kazuhiko Arase
8 | */
9 | internal class QRKanji extends QRData {
10 |
11 | public function QRKanji(data : String) {
12 | super(Mode.MODE_KANJI, data);
13 | }
14 |
15 | public override function write(buffer : BitBuffer) : void {
16 |
17 | var data : ByteArray = StringUtil.getBytes(getData(), QRUtil.getJISEncoding() );
18 |
19 | var i : int = 0;
20 |
21 | while (i + 1 < data.length) {
22 |
23 | var c : int = ( (0xff & data[i]) << 8) | (0xff & data[i + 1]);
24 |
25 | if (0x8140 <= c && c <= 0x9FFC) {
26 | c -= 0x8140;
27 | } else if (0xE040 <= c && c <= 0xEBBF) {
28 | c -= 0xC140;
29 | } else {
30 | throw new Error("illegal char at " + (i + 1) + "/" + c);
31 | }
32 |
33 | c = ( (c >>> 8) & 0xff) * 0xC0 + (c & 0xff);
34 |
35 | buffer.put(c, 13);
36 |
37 | i += 2;
38 | }
39 |
40 | if (i < data.length) {
41 | throw new Error("illegal char at " + (i + 1) );
42 | }
43 | }
44 |
45 | public override function getLength() : int {
46 | return Math.floor(StringUtil.getBytes(getData(), QRUtil.getJISEncoding() ).length / 2);
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/as3/src/as3/com/d_project/qrcode/QRMath.as:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode {
2 |
3 | /**
4 | * QRMath
5 | * @author Kazuhiko Arase
6 | */
7 | internal class QRMath {
8 |
9 | function QRMath() {
10 | throw new Error("");
11 | }
12 |
13 | private static var EXP_TABLE : Array;
14 | private static var LOG_TABLE : Array;
15 |
16 | private static var classInitialized : Boolean = initializeClass();
17 |
18 | private static function initializeClass() : Boolean {
19 |
20 | var i : int;
21 |
22 | EXP_TABLE = new Array(256);
23 |
24 | for (i = 0; i < 8; i++) {
25 | EXP_TABLE[i] = 1 << i;
26 | }
27 |
28 | for (i = 8; i < 256; i++) {
29 | EXP_TABLE[i] = EXP_TABLE[i - 4]
30 | ^ EXP_TABLE[i - 5]
31 | ^ EXP_TABLE[i - 6]
32 | ^ EXP_TABLE[i - 8];
33 | }
34 |
35 | LOG_TABLE = new Array(256);
36 | for (i = 0; i < 255; i++) {
37 | LOG_TABLE[EXP_TABLE[i] ] = i;
38 | }
39 |
40 | return true;
41 | }
42 |
43 | public static function glog(n : int) : int {
44 |
45 | if (n < 1) {
46 | throw new Error("log(" + n + ")");
47 | }
48 |
49 | return LOG_TABLE[n];
50 | }
51 |
52 | public static function gexp(n : int) : int {
53 |
54 | while (n < 0) {
55 | n += 255;
56 | }
57 |
58 | while (n >= 256) {
59 | n -= 255;
60 | }
61 |
62 | return EXP_TABLE[n];
63 | }
64 |
65 |
66 | }
67 |
68 | }
--------------------------------------------------------------------------------
/as3/src/as3/com/d_project/qrcode/QRNumber.as:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode {
2 |
3 | /**
4 | * QRNumber
5 | * @author Kazuhiko Arase
6 | */
7 | internal class QRNumber extends QRData {
8 |
9 | public function QRNumber(data : String) {
10 | super(Mode.MODE_NUMBER, data);
11 | }
12 |
13 | public override function write(buffer : BitBuffer) : void {
14 |
15 | var data : String = getData();
16 |
17 | var i : int = 0;
18 | var num : int;
19 |
20 | while (i + 2 < data.length) {
21 | num = parseInt(data.substring(i, i + 3) );
22 | buffer.put(num, 10);
23 | i += 3;
24 | }
25 |
26 | if (i < data.length) {
27 |
28 | if (data.length - i == 1) {
29 | num = parseInt(data.substring(i, i + 1) );
30 | buffer.put(num, 4);
31 | } else if (data.length - i == 2) {
32 | num = parseInt(data.substring(i, i + 2) );
33 | buffer.put(num, 7);
34 | }
35 |
36 | }
37 | }
38 |
39 | public override function getLength() : int {
40 | return getData().length;
41 | }
42 |
43 | private static function parseInt(s : String) : int {
44 | var num : int = 0;
45 | for (var i : int = 0; i < s.length; i++) {
46 | num = num * 10 + parseCharCode(s.charCodeAt(i) );
47 | }
48 | return num;
49 | }
50 |
51 | private static function parseCharCode(c : int) : int {
52 |
53 | if (getCharCode('0') <= c && c <= getCharCode('9') ) {
54 | return c - getCharCode('0') ;
55 | }
56 |
57 | throw new Error("illegal char :" + c);
58 | }
59 |
60 | private static function getCharCode(c : String) : int {
61 | return c.charCodeAt(0);
62 | }
63 |
64 | }
65 | }
--------------------------------------------------------------------------------
/as3/src/as3/com/d_project/qrcode/QRUtil.as:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode {
2 |
3 | import flash.utils.ByteArray;
4 |
5 | /**
6 | * QRUtil
7 | * @author Kazuhiko Arase
8 | */
9 | internal class QRUtil {
10 |
11 | public static function getJISEncoding() : String {
12 | return "shift_jis";
13 | }
14 |
15 | public static function getPatternPosition(typeNumber : int) : Array {
16 | return PATTERN_POSITION_TABLE[typeNumber - 1];
17 | }
18 |
19 | private static var PATTERN_POSITION_TABLE : Array =[
20 | [],
21 | [6, 18],
22 | [6, 22],
23 | [6, 26],
24 | [6, 30],
25 | [6, 34],
26 | [6, 22, 38],
27 | [6, 24, 42],
28 | [6, 26, 46],
29 | [6, 28, 50],
30 | [6, 30, 54],
31 | [6, 32, 58],
32 | [6, 34, 62],
33 | [6, 26, 46, 66],
34 | [6, 26, 48, 70],
35 | [6, 26, 50, 74],
36 | [6, 30, 54, 78],
37 | [6, 30, 56, 82],
38 | [6, 30, 58, 86],
39 | [6, 34, 62, 90],
40 | [6, 28, 50, 72, 94],
41 | [6, 26, 50, 74, 98],
42 | [6, 30, 54, 78, 102],
43 | [6, 28, 54, 80, 106],
44 | [6, 32, 58, 84, 110],
45 | [6, 30, 58, 86, 114],
46 | [6, 34, 62, 90, 118],
47 | [6, 26, 50, 74, 98, 122],
48 | [6, 30, 54, 78, 102, 126],
49 | [6, 26, 52, 78, 104, 130],
50 | [6, 30, 56, 82, 108, 134],
51 | [6, 34, 60, 86, 112, 138],
52 | [6, 30, 58, 86, 114, 142],
53 | [6, 34, 62, 90, 118, 146],
54 | [6, 30, 54, 78, 102, 126, 150],
55 | [6, 24, 50, 76, 102, 128, 154],
56 | [6, 28, 54, 80, 106, 132, 158],
57 | [6, 32, 58, 84, 110, 136, 162],
58 | [6, 26, 54, 82, 110, 138, 166],
59 | [6, 30, 58, 86, 114, 142, 170]
60 | ];
61 |
62 | private static var MAX_LENGTH : Array = [
63 | [ [41, 25, 17, 10], [34, 20, 14, 8], [27, 16, 11, 7], [17, 10, 7, 4] ],
64 | [ [77, 47, 32, 20], [63, 38, 26, 16], [48, 29, 20, 12], [34, 20, 14, 8] ],
65 | [ [127, 77, 53, 32], [101, 61, 42, 26], [77, 47, 32, 20], [58, 35, 24, 15] ],
66 | [ [187, 114, 78, 48], [149, 90, 62, 38], [111, 67, 46, 28], [82, 50, 34, 21] ],
67 | [ [255, 154, 106, 65], [202, 122, 84, 52], [144, 87, 60, 37], [106, 64, 44, 27] ],
68 | [ [322, 195, 134, 82], [255, 154, 106, 65], [178, 108, 74, 45], [139, 84, 58, 36] ],
69 | [ [370, 224, 154, 95], [293, 178, 122, 75], [207, 125, 86, 53], [154, 93, 64, 39] ],
70 | [ [461, 279, 192, 118], [365, 221, 152, 93], [259, 157, 108, 66], [202, 122, 84, 52] ],
71 | [ [552, 335, 230, 141], [432, 262, 180, 111], [312, 189, 130, 80], [235, 143, 98, 60] ],
72 | [ [652, 395, 271, 167], [513, 311, 213, 131], [364, 221, 151, 93], [288, 174, 119, 74] ]
73 | ];
74 |
75 | public static function getMaxLength(typeNumber : int, mode : int, errorCorrectLevel : int) : int {
76 |
77 | var t : int = typeNumber - 1;
78 | var e : int = 0;
79 | var m : int = 0;
80 |
81 | switch(errorCorrectLevel) {
82 | case ErrorCorrectLevel.L : e = 0; break;
83 | case ErrorCorrectLevel.M : e = 1; break;
84 | case ErrorCorrectLevel.Q : e = 2; break;
85 | case ErrorCorrectLevel.H : e = 3; break;
86 | default :
87 | throw new Error("e:" + errorCorrectLevel);
88 | }
89 |
90 | switch(mode) {
91 | case Mode.MODE_NUMBER : m = 0; break;
92 | case Mode.MODE_ALPHA_NUM : m = 1; break;
93 | case Mode.MODE_8BIT_BYTE : m = 2; break;
94 | case Mode.MODE_KANJI : m = 3; break;
95 | default :
96 | throw new Error("m:" + mode);
97 | }
98 |
99 | return MAX_LENGTH[t][e][m];
100 | }
101 |
102 |
103 | /**
104 | * エラー訂正多項式を取得する。
105 | */
106 | public static function getErrorCorrectPolynomial(errorCorrectLength : int) : Polynomial{
107 |
108 | var a : Polynomial = new Polynomial([1]);
109 |
110 | for (var i : int = 0; i < errorCorrectLength; i++) {
111 | a = a.multiply(new Polynomial([1, QRMath.gexp(i)]) );
112 | }
113 |
114 | return a;
115 | }
116 |
117 | /**
118 | * 指定されたパターンのマスクを取得する。
119 | */
120 | public static function getMask(maskPattern : int, i : int, j : int) : Boolean {
121 |
122 | switch (maskPattern) {
123 |
124 | case MaskPattern.PATTERN000 : return (i + j) % 2 == 0;
125 | case MaskPattern.PATTERN001 : return i % 2 == 0;
126 | case MaskPattern.PATTERN010 : return j % 3 == 0;
127 | case MaskPattern.PATTERN011 : return (i + j) % 3 == 0;
128 | case MaskPattern.PATTERN100 : return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0;
129 | case MaskPattern.PATTERN101 : return (i * j) % 2 + (i * j) % 3 == 0;
130 | case MaskPattern.PATTERN110 : return ( (i * j) % 2 + (i * j) % 3) % 2 == 0;
131 | case MaskPattern.PATTERN111 : return ( (i * j) % 3 + (i + j) % 2) % 2 == 0;
132 |
133 | default :
134 | throw new Error("mask:" + maskPattern);
135 | }
136 | }
137 |
138 | /**
139 | * 失点を取得する
140 | */
141 | public static function getLostPoint(qrCode : QRCode) : int {
142 |
143 | var moduleCount : int = qrCode.getModuleCount();
144 |
145 | var lostPoint : int = 0;
146 |
147 | var row : int;
148 | var col : int;
149 |
150 | // LEVEL1
151 |
152 | for (row = 0; row < moduleCount; row++) {
153 |
154 | for (col = 0; col < moduleCount; col++) {
155 |
156 | var sameCount : int = 0;
157 | var dark : Boolean = qrCode.isDark(row, col);
158 |
159 | for (var r : int = -1; r <= 1; r++) {
160 |
161 | if (row + r < 0 || moduleCount <= row + r) {
162 | continue;
163 | }
164 |
165 | for (var c : int = -1; c <= 1; c++) {
166 |
167 | if (col + c < 0 || moduleCount <= col + c) {
168 | continue;
169 | }
170 |
171 | if (r == 0 && c == 0) {
172 | continue;
173 | }
174 |
175 | if (dark == qrCode.isDark(row + r, col + c) ) {
176 | sameCount++;
177 | }
178 | }
179 | }
180 |
181 | if (sameCount > 5) {
182 | lostPoint += (3 + sameCount - 5);
183 | }
184 | }
185 | }
186 |
187 | // LEVEL2
188 |
189 | for (row = 0; row < moduleCount - 1; row++) {
190 | for (col = 0; col < moduleCount - 1; col++) {
191 | var count : int = 0;
192 | if (qrCode.isDark(row, col ) ) count++;
193 | if (qrCode.isDark(row + 1, col ) ) count++;
194 | if (qrCode.isDark(row, col + 1) ) count++;
195 | if (qrCode.isDark(row + 1, col + 1) ) count++;
196 | if (count == 0 || count == 4) {
197 | lostPoint += 3;
198 | }
199 | }
200 | }
201 |
202 | // LEVEL3
203 |
204 | for (row = 0; row < moduleCount; row++) {
205 | for (col = 0; col < moduleCount - 6; col++) {
206 | if (qrCode.isDark(row, col)
207 | && !qrCode.isDark(row, col + 1)
208 | && qrCode.isDark(row, col + 2)
209 | && qrCode.isDark(row, col + 3)
210 | && qrCode.isDark(row, col + 4)
211 | && !qrCode.isDark(row, col + 5)
212 | && qrCode.isDark(row, col + 6) ) {
213 | lostPoint += 40;
214 | }
215 | }
216 | }
217 |
218 | for (col = 0; col < moduleCount; col++) {
219 | for (row = 0; row < moduleCount - 6; row++) {
220 | if (qrCode.isDark(row, col)
221 | && !qrCode.isDark(row + 1, col)
222 | && qrCode.isDark(row + 2, col)
223 | && qrCode.isDark(row + 3, col)
224 | && qrCode.isDark(row + 4, col)
225 | && !qrCode.isDark(row + 5, col)
226 | && qrCode.isDark(row + 6, col) ) {
227 | lostPoint += 40;
228 | }
229 | }
230 | }
231 |
232 | // LEVEL4
233 |
234 | var darkCount : int = 0;
235 |
236 | for (col = 0; col < moduleCount; col++) {
237 | for (row = 0; row < moduleCount; row++) {
238 | if (qrCode.isDark(row, col) ) {
239 | darkCount++;
240 | }
241 | }
242 | }
243 |
244 | var ratio : int = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
245 | lostPoint += ratio * 10;
246 |
247 | return lostPoint;
248 | }
249 |
250 | public static function getMode(s : String) : int {
251 | if (isAlphaNum(s) ) {
252 | if (isNumber(s) ) {
253 | return Mode.MODE_NUMBER;
254 | }
255 | return Mode.MODE_ALPHA_NUM;
256 | } else if (isKanji(s) ) {
257 | return Mode.MODE_KANJI;
258 | } else {
259 | return Mode.MODE_8BIT_BYTE;
260 | }
261 | }
262 |
263 | private static function isNumber(s : String) : Boolean {
264 | for (var i : int = 0; i < s.length; i++) {
265 | var c : String = s.charAt(i);
266 | if (!('0' <= c && c <= '9') ) {
267 | return false;
268 | }
269 | }
270 | return true;
271 | }
272 |
273 | private static function isAlphaNum(s : String) : Boolean {
274 | for (var i : int = 0; i < s.length; i++) {
275 | var c : String = s.charAt(i);
276 | if (!('0' <= c && c <= '9') && !('A' <= c && c <= 'Z') && " $%*+-./:".indexOf(c) == -1) {
277 | return false;
278 | }
279 | }
280 | return true;
281 | }
282 |
283 | private static function isKanji(s : String) : Boolean {
284 |
285 | var data : ByteArray = StringUtil.getBytes(s, QRUtil.getJISEncoding() );
286 |
287 | var i : int = 0;
288 |
289 | while (i + 1 < data.length) {
290 |
291 | var c : int = ( (0xff & data[i]) << 8) | (0xff & data[i + 1]);
292 |
293 | if (!(0x8140 <= c && c <= 0x9FFC) && !(0xE040 <= c && c <= 0xEBBF) ) {
294 | return false;
295 | }
296 |
297 | i += 2;
298 | }
299 |
300 | if (i < data.length) {
301 | return false;
302 | }
303 |
304 | return true;
305 | }
306 |
307 | private static const G15 : int = (1 << 10) | (1 << 8) | (1 << 5)
308 | | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
309 |
310 | private static const G18 : int = (1 << 12) | (1 << 11) | (1 << 10)
311 | | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);
312 |
313 | private static const G15_MASK : int = (1 << 14) | (1 << 12) | (1 << 10)
314 | | (1 << 4) | (1 << 1);
315 |
316 | public static function getBCHTypeInfo(data : int) : int {
317 | var d : int = data << 10;
318 | while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {
319 | d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) );
320 | }
321 | return ( (data << 10) | d) ^ G15_MASK;
322 | }
323 |
324 | public static function getBCHTypeNumber(data : int) : int {
325 | var d : int = data << 12;
326 | while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {
327 | d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) );
328 | }
329 | return (data << 12) | d;
330 | }
331 |
332 | private static function getBCHDigit(data : int) : int {
333 |
334 | var digit : int = 0;
335 |
336 | while (data != 0) {
337 | digit++;
338 | data >>>= 1;
339 | }
340 |
341 | return digit;
342 |
343 | }
344 | }
345 | }
--------------------------------------------------------------------------------
/as3/src/as3/com/d_project/qrcode/RSBlock.as:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode {
2 |
3 | /**
4 | * RSBlock
5 | * @author Kazuhiko Arase
6 | */
7 | internal class RSBlock {
8 |
9 | private static var RS_BLOCK_TABLE : Array = [
10 |
11 | // L
12 | // M
13 | // Q
14 | // H
15 |
16 | // 1
17 | [1, 26, 19],
18 | [1, 26, 16],
19 | [1, 26, 13],
20 | [1, 26, 9],
21 |
22 | // 2
23 | [1, 44, 34],
24 | [1, 44, 28],
25 | [1, 44, 22],
26 | [1, 44, 16],
27 |
28 | // 3
29 | [1, 70, 55],
30 | [1, 70, 44],
31 | [2, 35, 17],
32 | [2, 35, 13],
33 |
34 | // 4
35 | [1, 100, 80],
36 | [2, 50, 32],
37 | [2, 50, 24],
38 | [4, 25, 9],
39 |
40 | // 5
41 | [1, 134, 108],
42 | [2, 67, 43],
43 | [2, 33, 15, 2, 34, 16],
44 | [2, 33, 11, 2, 34, 12],
45 |
46 | // 6
47 | [2, 86, 68],
48 | [4, 43, 27],
49 | [4, 43, 19],
50 | [4, 43, 15],
51 |
52 | // 7
53 | [2, 98, 78],
54 | [4, 49, 31],
55 | [2, 32, 14, 4, 33, 15],
56 | [4, 39, 13, 1, 40, 14],
57 |
58 | // 8
59 | [2, 121, 97],
60 | [2, 60, 38, 2, 61, 39],
61 | [4, 40, 18, 2, 41, 19],
62 | [4, 40, 14, 2, 41, 15],
63 |
64 | // 9
65 | [2, 146, 116],
66 | [3, 58, 36, 2, 59, 37],
67 | [4, 36, 16, 4, 37, 17],
68 | [4, 36, 12, 4, 37, 13],
69 |
70 | // 10
71 | [2, 86, 68, 2, 87, 69],
72 | [4, 69, 43, 1, 70, 44],
73 | [6, 43, 19, 2, 44, 20],
74 | [6, 43, 15, 2, 44, 16]
75 |
76 | ];
77 |
78 | private var totalCount : int;
79 | private var dataCount : int;
80 |
81 | public function RSBlock(totalCount : int, dataCount : int) {
82 | this.totalCount = totalCount;
83 | this.dataCount = dataCount;
84 | }
85 |
86 | public function getDataCount() : int {
87 | return dataCount;
88 | }
89 |
90 | public function getTotalCount() : int {
91 | return totalCount;
92 | }
93 |
94 | public static function getRSBlocks(typeNumber : int, errorCorrectLevel : int) : Array {
95 |
96 | var rsBlock : Array = getRsBlockTable(typeNumber, errorCorrectLevel);
97 | var length : int = Math.floor(rsBlock.length / 3);
98 | var list : Array = new Array();
99 |
100 | for (var i : int = 0; i < length; i++) {
101 |
102 | var count : int = rsBlock[i * 3 + 0];
103 | var totalCount : int = rsBlock[i * 3 + 1];
104 | var dataCount : int = rsBlock[i * 3 + 2];
105 |
106 | for (var j : int = 0; j < count; j++) {
107 | list.push(new RSBlock(totalCount, dataCount) );
108 | }
109 | }
110 |
111 | return list;
112 | }
113 |
114 | private static function getRsBlockTable(typeNumber : int, errorCorrectLevel : int) : Array {
115 |
116 | try {
117 |
118 | switch(errorCorrectLevel) {
119 | case ErrorCorrectLevel.L :
120 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
121 | case ErrorCorrectLevel.M :
122 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
123 | case ErrorCorrectLevel.Q :
124 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
125 | case ErrorCorrectLevel.H :
126 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
127 | default :
128 | break;
129 | }
130 |
131 | } catch(e : Error) {
132 | }
133 |
134 | throw new Error("tn:" + typeNumber + "/ecl:" + errorCorrectLevel);
135 | }
136 |
137 | }
138 |
139 | }
--------------------------------------------------------------------------------
/as3/src/as3/com/d_project/qrcode/StringUtil.as:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode {
2 |
3 | import flash.utils.ByteArray;
4 |
5 | /**
6 | * StringUtil
7 | * @author Kazuhiko Arase
8 | */
9 | internal class StringUtil {
10 |
11 | public static function getBytes(s : String, encoding : String) : ByteArray {
12 | var b : ByteArray = new ByteArray();
13 | b.writeMultiByte(s, encoding);
14 | return b;
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/as3/src/as3/com/d_project/qrcode/mx/QRCode.as:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode.mx {
2 |
3 | import mx.core.UIComponent;
4 | import flash.display.Graphics;
5 |
6 | import com.d_project.qrcode.ErrorCorrectLevel;
7 |
8 |
9 | /**
10 | * QRコード.
11 | * @author Kazuhiko Arase
12 | */
13 | public class QRCode extends UIComponent {
14 |
15 | private var qr : com.d_project.qrcode.QRCode;
16 |
17 | private var _text : String;
18 |
19 | [Inspectable(enumeration="L,M,Q,H", defaultValue="H")]
20 | public var errorCorrectLevel : String = "H";
21 |
22 | public function QRCode() {
23 | _text = "QRCode";
24 | qr = null;
25 | }
26 |
27 | public function get text() : String {
28 | return _text;
29 | }
30 |
31 | public function set text(value : String) : void {
32 | _text = value;
33 | qr = null;
34 | invalidateDisplayList();
35 | }
36 |
37 | protected override function updateDisplayList(unscaledWidth : Number, unscaledHeight : Number) : void {
38 |
39 | var padding : Number = 10;
40 |
41 | var size : Number = Math.min(unscaledWidth, unscaledHeight) - padding * 2;
42 | var xOffset : Number = (unscaledWidth - size) / 2;
43 | var yOffset : Number = (unscaledHeight - size) / 2;
44 |
45 | if (qr == null) {
46 | qr = com.d_project.qrcode.QRCode.getMinimumQRCode(text, ErrorCorrectLevel[errorCorrectLevel]);
47 | }
48 |
49 | var cs : Number = size / qr.getModuleCount();
50 |
51 | var g : Graphics = graphics;
52 |
53 | g.beginFill(0xffffff);
54 | g.drawRect(0, 0, unscaledWidth, unscaledHeight);
55 | g.endFill();
56 |
57 | for (var row : int = 0; row < qr.getModuleCount(); row++) {
58 | for (var col : int = 0; col < qr.getModuleCount(); col++) {
59 | g.beginFill( (qr.isDark(row, col)? 0 : 0xffffff) );
60 | g.drawRect(cs * col + xOffset, cs * row + yOffset, cs, cs);
61 | g.endFill();
62 | }
63 | }
64 | }
65 | }
66 | }
67 |
68 |
--------------------------------------------------------------------------------
/as3/src/assets/README.txt:
--------------------------------------------------------------------------------
1 | QRCode for ActionScript3
2 |
3 | Copyright (c) 2009 Kazuhiko Arase
4 |
5 | URL: http://www.d-project.com/
6 |
7 | Licensed under the MIT license:
8 | http://www.opensource.org/licenses/mit-license.php
9 |
10 | The word "QR Code" is registered trademark of
11 | DENSO WAVE INCORPORATED
12 | http://www.denso-wave.com/qrcode/faqpatent-e.html
13 |
14 |
15 | -- REQUIREMENTS
16 |
17 | FlashPlayer 9.0.28 or above
18 |
19 | -- CONTENTS
20 |
21 | README.txt - this file
22 | qrcode.swc - library
23 | sample - sample
24 | apidocs - API document
25 |
--------------------------------------------------------------------------------
/as3/src/assets/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/as3/src/build.xml:
--------------------------------------------------------------------------------
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 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
101 |
102 |
103 |
104 | #ffffff
105 |
106 | true
107 |
108 |
109 |
114 |
115 |
116 |
117 | #ffffff
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/as3/src/sample/QRCodeSample1.as:
--------------------------------------------------------------------------------
1 | package {
2 |
3 | import com.d_project.qrcode.ErrorCorrectLevel;
4 | import com.d_project.qrcode.QRCode;
5 |
6 | import flash.display.Graphics;
7 | import flash.display.Sprite;
8 |
9 | public class QRCodeSample1 extends Sprite {
10 |
11 | public function QRCodeSample1() {
12 |
13 | var width : Number = 200;
14 | var height : Number = 200;
15 | var padding : Number = 10;
16 |
17 | var size : Number = Math.min(width, height) - padding * 2;
18 | var xOffset : Number = (width - size) / 2;
19 | var yOffset : Number = (height - size) / 2;
20 |
21 | var qr : QRCode = QRCode.getMinimumQRCode("AS3ならば、文字コードの扱いも簡単!", ErrorCorrectLevel.H);
22 |
23 | var cs : Number = size / qr.getModuleCount();
24 |
25 | var g : Graphics = graphics;
26 |
27 | for (var row : int = 0; row < qr.getModuleCount(); row++) {
28 | for (var col : int = 0; col < qr.getModuleCount(); col++) {
29 | g.beginFill( (qr.isDark(row, col)? 0 : 0xffffff) );
30 | g.drawRect(cs * col + xOffset, cs * row + yOffset, cs, cs);
31 | g.endFill();
32 | }
33 | }
34 | }
35 | }
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/as3/src/sample/QRCodeSample2.mxml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/hack/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/**
2 | **/*hhast.parser-cache
3 | .var/
4 |
--------------------------------------------------------------------------------
/hack/.hhconfig:
--------------------------------------------------------------------------------
1 | ignored_paths = [ "vendor/.+/tests/.+", "vendor/.+/bin/.+"]
2 | hackfmt.line_width = 80
3 | hackfmt.indent_width = 4
4 | allowed_decl_fixme_codes = 2053, 4047
5 | allowed_fixme_codes_strict = 2049, 2053, 4027, 4047, 4104, 4107, 4110, 4128, 4188, 4323
6 |
--------------------------------------------------------------------------------
/hack/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "kazuhikoarase/qrcode-generator",
3 | "description": "A Hack port of the PHP 5 program Kazuhikoarase\\QrcodeGenerator",
4 | "require": {
5 | "hhvm": "^4.32"
6 | },
7 | "require-dev": {
8 | "hhvm/hhvm-autoload": "^2.0|^3.0",
9 | "hhvm/hhast": "^4.41"
10 | }
11 | }
--------------------------------------------------------------------------------
/hack/hh_autoload.json:
--------------------------------------------------------------------------------
1 | {
2 | "roots": [
3 | "src/"
4 | ],
5 | "devRoots": [
6 | "samples/"
7 | ],
8 | "devFailureHandler": "Facebook\\AutoloadMap\\HHClientFallbackHandler"
9 | }
--------------------------------------------------------------------------------
/hack/hhast-lint.json:
--------------------------------------------------------------------------------
1 | {
2 | "roots": [
3 | "src/"
4 | ],
5 | "builtinLinters": "all",
6 | }
--------------------------------------------------------------------------------
/hack/hhast_lint.json:
--------------------------------------------------------------------------------
1 | {
2 | "roots": ["src"],
3 | "builtinLinters": "all"
4 | }
5 |
--------------------------------------------------------------------------------
/hack/samples/sample.html:
--------------------------------------------------------------------------------
1 | sample_html.php
2 |
3 | sample_image.php
4 |
5 | sample_custom.php
6 |
--------------------------------------------------------------------------------
/hack/samples/sample_custom.php:
--------------------------------------------------------------------------------
1 | >
6 | function sample_custom(): noreturn {
7 | require_once __DIR__.'/../vendor/autoload.hack';
8 | \Facebook\AutoloadMap\initialize();
9 | $qr = QrcodeGenerator\QRCode::getMinimumQRCode(
10 | "日本語のQR 1234:! 漢字",
11 | QrcodeGenerator\ErrorCorrectionPercentage::SEVEN,
12 | );
13 |
14 | header("Content-type: text/xml");
15 |
16 | print("");
17 |
18 | for ($r = 0; $r < $qr->getModuleCount(); $r++) {
19 | print("");
20 | for ($c = 0; $c < $qr->getModuleCount(); $c++) {
21 | print($qr->isDark($r, $c) ? "1" : "0");
22 | }
23 | print("");
24 | }
25 |
26 | print("");
27 |
28 | exit(0);
29 | }
30 |
--------------------------------------------------------------------------------
/hack/samples/sample_html.php:
--------------------------------------------------------------------------------
1 | >
6 | function sample_html(): noreturn {
7 | require_once __DIR__.'/../vendor/autoload.hack';
8 | \Facebook\AutoloadMap\initialize();
9 | //---------------------------------------------------------
10 |
11 | print('');
12 |
13 | // QR in Japanese 1234:! Kanji
14 | print("
日本語のQR 1234:! 漢字
");
15 |
16 | $qr = new QrcodeGenerator\QRCode();
17 | // QR_ERROR_CORRECT_LEVEL_L : 7%
18 | // QR_ERROR_CORRECT_LEVEL_M : 15%
19 | // QR_ERROR_CORRECT_LEVEL_Q : 25%
20 | // QR_ERROR_CORRECT_LEVEL_H : 30%
21 | $qr->setErrorCorrectLevel(QrcodeGenerator\ErrorCorrectionPercentage::SEVEN);
22 | $qr->setTypeNumber(4);
23 | $qr->addData("日本語のQR 1234:! 漢字");
24 | $qr->make();
25 | $qr->printHTML();
26 |
27 | //---------------------------------------------------------
28 |
29 | // QR quick 1234:!
30 | print("QRクイック 1234:!
");
31 |
32 | $qr = QrcodeGenerator\QRCode::getMinimumQRCode(
33 | "QRクイック",
34 | QrcodeGenerator\ErrorCorrectionPercentage::SEVEN,
35 | );
36 | $qr->printHTML();
37 |
38 | exit(0);
39 | }
40 |
--------------------------------------------------------------------------------
/hack/samples/sample_image.php:
--------------------------------------------------------------------------------
1 | >
7 | function sample_image(): noreturn {
8 | require_once __DIR__.'/../vendor/autoload.hack';
9 | \Facebook\AutoloadMap\initialize();
10 | $qr = QrcodeGenerator\QRCode::getMinimumQRCode(
11 | "日本語のQR 1234:! 漢字",
12 | QrcodeGenerator\ErrorCorrectionPercentage::SEVEN,
13 | );
14 |
15 | $im = $qr->createImage(2, 4);
16 |
17 | header("Content-type: image/gif");
18 | imagegif($im);
19 |
20 | imagedestroy($im);
21 |
22 | exit(0);
23 | }
24 |
--------------------------------------------------------------------------------
/hack/unit_test.diffme.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kazuhikoarase/qrcode-generator/0e51e6310a34b5e4f70280533b3d43e1fc6a0b16/hack/unit_test.diffme.gif
--------------------------------------------------------------------------------
/java/.gitignore:
--------------------------------------------------------------------------------
1 | /.gradle
2 | /.settings
3 | /.classpath
4 | /.project
5 | /bin
6 | /build
7 | /gradle.properties
8 |
--------------------------------------------------------------------------------
/java/README.txt:
--------------------------------------------------------------------------------
1 | QRCode for Java
2 |
3 | Copyright (c) 2009 Kazuhiko Arase
4 |
5 | URL: http://www.d-project.com/
6 |
7 | Licensed under the MIT license:
8 | http://www.opensource.org/licenses/mit-license.php
9 |
10 | The word "QR Code" is registered trademark of
11 | DENSO WAVE INCORPORATED
12 | http://www.denso-wave.com/qrcode/faqpatent-e.html
13 |
14 |
15 | -- REQUIREMENTS
16 |
17 | Java Runtime Environment (JRE) 1.6 or above
18 |
19 | -- CONTENTS
20 |
21 | README.txt - this file
22 | qrcode.jar - library
23 | sample
24 | /QRCodeSample.war - sample web application
25 | apidocs - API document
26 |
--------------------------------------------------------------------------------
/java/build.gradle:
--------------------------------------------------------------------------------
1 |
2 | apply plugin: 'java'
3 |
4 | sourceCompatibility = 1.6
5 |
6 | compileJava.options.encoding = 'UTF-8'
7 | compileTestJava.options.encoding = 'UTF-8'
8 |
9 | jar {
10 | baseName "qrcode"
11 | }
12 |
13 | task all {
14 | dependsOn 'clean'
15 | dependsOn 'jar'
16 | }
17 |
18 | /*
19 | uploadArchives {
20 | repositories {
21 | flatDir {
22 | dirs 'repos'
23 | }
24 | }
25 | }
26 | */
27 |
28 | repositories {
29 | mavenCentral()
30 | }
31 |
32 | dependencies {
33 | implementation 'javax.servlet:javax.servlet-api:3.0.1'
34 | testImplementation 'junit:junit:4.12'
35 | }
36 |
--------------------------------------------------------------------------------
/java/src/main/java/com/d_project/qrcode/BitBuffer.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | /**
4 | * BitBuffer
5 | * @author Kazuhiko Arase
6 | */
7 | class BitBuffer {
8 |
9 | private byte[] buffer;
10 | private int length;
11 | private int inclements;
12 |
13 | public BitBuffer() {
14 | inclements = 32;
15 | buffer = new byte[inclements];
16 | length = 0;
17 | }
18 |
19 | public byte[] getBuffer() {
20 | return buffer;
21 | }
22 |
23 | public int getLengthInBits() {
24 | return length;
25 | }
26 |
27 | public String toString() {
28 | StringBuilder buffer = new StringBuilder();
29 | for (int i = 0; i < getLengthInBits(); i++) {
30 | buffer.append(get(i)? '1' : '0');
31 | }
32 | return buffer.toString();
33 | }
34 |
35 | private boolean get(int index) {
36 | return ( (buffer[index / 8] >>> (7 - index % 8) ) & 1) == 1;
37 | }
38 |
39 | public void put(int num, int length) {
40 | for (int i = 0; i < length; i++) {
41 | put( ( (num >>> (length - i - 1) ) & 1) == 1);
42 | }
43 | }
44 |
45 | public void put(boolean bit) {
46 |
47 | if (length == buffer.length * 8) {
48 | byte[] newBuffer = new byte[buffer.length + inclements];
49 | System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
50 | buffer = newBuffer;
51 | }
52 |
53 | if (bit) {
54 | buffer[length / 8] |= (0x80 >>> (length % 8) );
55 | }
56 |
57 | length++;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/java/src/main/java/com/d_project/qrcode/ErrorCorrectionLevel.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | /**
4 | * 誤り訂正レベル.
5 | * @author Kazuhiko Arase
6 | */
7 | public interface ErrorCorrectionLevel {
8 |
9 | /**
10 | * 復元能力 7%.
11 | */
12 | int L = 1;
13 |
14 | /**
15 | * 復元能力 15%.
16 | */
17 | int M = 0;
18 |
19 | /**
20 | * 復元能力 25%.
21 | */
22 | int Q = 3;
23 |
24 | /**
25 | * 復元能力 30%.
26 | */
27 | int H = 2;
28 | }
29 |
--------------------------------------------------------------------------------
/java/src/main/java/com/d_project/qrcode/MaskPattern.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | /**
4 | * マスクパターン.
5 | * @author Kazuhiko Arase
6 | */
7 | interface MaskPattern {
8 |
9 | /**
10 | * マスクパターン000
11 | */
12 | int PATTERN000 = 0;
13 |
14 | /**
15 | * マスクパターン001
16 | */
17 | int PATTERN001 = 1;
18 |
19 | /**
20 | * マスクパターン010
21 | */
22 | int PATTERN010 = 2;
23 |
24 | /**
25 | * マスクパターン011
26 | */
27 | int PATTERN011 = 3;
28 |
29 | /**
30 | * マスクパターン100
31 | */
32 | int PATTERN100 = 4;
33 |
34 | /**
35 | * マスクパターン101
36 | */
37 | int PATTERN101 = 5;
38 |
39 | /**
40 | * マスクパターン110
41 | */
42 | int PATTERN110 = 6;
43 |
44 | /**
45 | * マスクパターン111
46 | */
47 | int PATTERN111 = 7;
48 | }
49 |
--------------------------------------------------------------------------------
/java/src/main/java/com/d_project/qrcode/Mode.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | /**
4 | * モード.
5 | * @author Kazuhiko Arase
6 | */
7 | public interface Mode {
8 |
9 | /**
10 | * 数値モード
11 | */
12 | int MODE_NUMBER = 1 << 0;
13 |
14 | /**
15 | * 英数字モード
16 | */
17 | int MODE_ALPHA_NUM = 1 << 1;
18 |
19 | /**
20 | * 8ビットバイトモード
21 | */
22 | int MODE_8BIT_BYTE = 1 << 2;
23 |
24 | /**
25 | * 漢字モード
26 | */
27 | int MODE_KANJI = 1 << 3;
28 | }
29 |
--------------------------------------------------------------------------------
/java/src/main/java/com/d_project/qrcode/Polynomial.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | /**
4 | * Polynomial
5 | * @author Kazuhiko Arase
6 | */
7 | class Polynomial {
8 |
9 | private final int[] num;
10 |
11 | public Polynomial(int[] num) {
12 | this(num, 0);
13 | }
14 |
15 | public Polynomial(int[] num, int shift) {
16 |
17 | int offset = 0;
18 |
19 | while (offset < num.length && num[offset] == 0) {
20 | offset++;
21 | }
22 |
23 | this.num = new int[num.length - offset + shift];
24 | System.arraycopy(num, offset, this.num, 0, num.length - offset);
25 | }
26 |
27 | public int get(int index) {
28 | return num[index];
29 | }
30 |
31 | public int getLength() {
32 | return num.length;
33 | }
34 |
35 | public String toString() {
36 |
37 | StringBuilder buffer = new StringBuilder();
38 |
39 | for (int i = 0; i < getLength(); i++) {
40 | if (i > 0) {
41 | buffer.append(",");
42 | }
43 | buffer.append(get(i) );
44 | }
45 |
46 | return buffer.toString();
47 | }
48 |
49 | public String toLogString() {
50 |
51 | StringBuilder buffer = new StringBuilder();
52 |
53 | for (int i = 0; i < getLength(); i++) {
54 | if (i > 0) {
55 | buffer.append(",");
56 | }
57 | buffer.append(QRMath.glog(get(i) ) );
58 |
59 | }
60 |
61 | return buffer.toString();
62 | }
63 |
64 | public Polynomial multiply(Polynomial e) {
65 |
66 | int[] num = new int[getLength() + e.getLength() - 1];
67 |
68 | for (int i = 0; i < getLength(); i++) {
69 | for (int j = 0; j < e.getLength(); j++) {
70 | num[i + j] ^= QRMath.gexp(QRMath.glog(get(i) ) + QRMath.glog(e.get(j) ) );
71 | }
72 | }
73 |
74 | return new Polynomial(num);
75 | }
76 |
77 | public Polynomial mod(Polynomial e) {
78 |
79 | if (getLength() - e.getLength() < 0) {
80 | return this;
81 | }
82 |
83 | // 最上位桁の比率
84 | int ratio = QRMath.glog(get(0) ) - QRMath.glog(e.get(0) );
85 |
86 | // コピー作成
87 | int[] num = new int[getLength()];
88 | for (int i = 0; i < getLength(); i++) {
89 | num[i] = get(i);
90 | }
91 |
92 | // 引き算して余りを計算
93 | for (int i = 0; i < e.getLength(); i++) {
94 | num[i] ^= QRMath.gexp(QRMath.glog(e.get(i) ) + ratio);
95 | }
96 |
97 | // 再帰計算
98 | return new Polynomial(num).mod(e);
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/java/src/main/java/com/d_project/qrcode/QR8BitByte.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | import java.io.UnsupportedEncodingException;
4 |
5 | /**
6 | * QR8BitByte
7 | * @author Kazuhiko Arase
8 | */
9 | class QR8BitByte extends QRData {
10 |
11 | public QR8BitByte(String data) {
12 | super(Mode.MODE_8BIT_BYTE, data);
13 | }
14 |
15 | public void write(BitBuffer buffer) {
16 |
17 | try {
18 |
19 | byte[] data = getData().getBytes(QRCode.get8BitByteEncoding() );
20 |
21 | for (int i = 0; i < data.length; i++) {
22 | buffer.put(data[i], 8);
23 | }
24 |
25 | } catch(UnsupportedEncodingException e) {
26 | throw new RuntimeException(e.getMessage() );
27 | }
28 | }
29 |
30 | public int getLength() {
31 | try {
32 | return getData().getBytes(QRCode.get8BitByteEncoding() ).length;
33 | } catch(UnsupportedEncodingException e) {
34 | throw new RuntimeException(e.getMessage() );
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/java/src/main/java/com/d_project/qrcode/QRAlphaNum.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | /**
4 | * QRAlphaNum
5 | * @author Kazuhiko Arase
6 | */
7 | class QRAlphaNum extends QRData {
8 |
9 | public QRAlphaNum(String data) {
10 | super(Mode.MODE_ALPHA_NUM, data);
11 | }
12 |
13 | public void write(BitBuffer buffer) {
14 |
15 | char[] c = getData().toCharArray();
16 |
17 | int i = 0;
18 |
19 | while (i + 1 < c.length) {
20 | buffer.put(getCode(c[i]) * 45 + getCode(c[i + 1]), 11);
21 | i += 2;
22 | }
23 |
24 | if (i < c.length) {
25 | buffer.put(getCode(c[i]), 6);
26 | }
27 | }
28 |
29 | public int getLength() {
30 | return getData().length();
31 | }
32 |
33 | private static int getCode(char c) {
34 |
35 | if ('0' <= c && c <= '9') {
36 | return c - '0';
37 | } else if ('A' <= c && c <= 'Z') {
38 | return c - 'A' + 10;
39 | } else {
40 | switch (c) {
41 | case ' ' : return 36;
42 | case '$' : return 37;
43 | case '%' : return 38;
44 | case '*' : return 39;
45 | case '+' : return 40;
46 | case '-' : return 41;
47 | case '.' : return 42;
48 | case '/' : return 43;
49 | case ':' : return 44;
50 | default :
51 | throw new IllegalArgumentException("illegal char :" + c);
52 | }
53 | }
54 |
55 | }
56 | }
--------------------------------------------------------------------------------
/java/src/main/java/com/d_project/qrcode/QRData.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | /**
4 | * QRData
5 | * @author Kazuhiko Arase
6 | */
7 | abstract class QRData {
8 |
9 | private final int mode;
10 |
11 | private final String data;
12 |
13 | protected QRData(int mode, String data) {
14 | this.mode = mode;
15 | this.data = data;
16 | }
17 |
18 | public int getMode() {
19 | return mode;
20 | }
21 |
22 | public String getData() {
23 | return data;
24 | }
25 |
26 | public abstract int getLength();
27 |
28 | public abstract void write(BitBuffer buffer);
29 |
30 | /**
31 | * 型番及びモードに対するビット長を取得する。
32 | */
33 | public int getLengthInBits(int type) {
34 |
35 | if (1 <= type && type < 10) {
36 |
37 | // 1 - 9
38 |
39 | switch(mode) {
40 | case Mode.MODE_NUMBER : return 10;
41 | case Mode.MODE_ALPHA_NUM : return 9;
42 | case Mode.MODE_8BIT_BYTE : return 8;
43 | case Mode.MODE_KANJI : return 8;
44 | default :
45 | throw new IllegalArgumentException("mode:" + mode);
46 | }
47 |
48 | } else if (type < 27) {
49 |
50 | // 10 - 26
51 |
52 | switch(mode) {
53 | case Mode.MODE_NUMBER : return 12;
54 | case Mode.MODE_ALPHA_NUM : return 11;
55 | case Mode.MODE_8BIT_BYTE : return 16;
56 | case Mode.MODE_KANJI : return 10;
57 | default :
58 | throw new IllegalArgumentException("mode:" + mode);
59 | }
60 |
61 | } else if (type < 41) {
62 |
63 | // 27 - 40
64 |
65 | switch(mode) {
66 | case Mode.MODE_NUMBER : return 14;
67 | case Mode.MODE_ALPHA_NUM : return 13;
68 | case Mode.MODE_8BIT_BYTE : return 16;
69 | case Mode.MODE_KANJI : return 12;
70 | default :
71 | throw new IllegalArgumentException("mode:" + mode);
72 | }
73 |
74 | } else {
75 | throw new IllegalArgumentException("type:" + type);
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/java/src/main/java/com/d_project/qrcode/QRKanji.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | import java.io.UnsupportedEncodingException;
4 |
5 | /**
6 | * QRKanji
7 | * @author Kazuhiko Arase
8 | */
9 | class QRKanji extends QRData {
10 |
11 | public QRKanji(String data) {
12 | super(Mode.MODE_KANJI, data);
13 | }
14 |
15 | public void write(BitBuffer buffer) {
16 |
17 | try {
18 |
19 | byte[] data = getData().getBytes(QRUtil.getJISEncoding() );
20 |
21 | int i = 0;
22 |
23 | while (i + 1 < data.length) {
24 |
25 | int c = ( (0xff & data[i]) << 8) | (0xff & data[i + 1]);
26 |
27 | if (0x8140 <= c && c <= 0x9FFC) {
28 | c -= 0x8140;
29 | } else if (0xE040 <= c && c <= 0xEBBF) {
30 | c -= 0xC140;
31 | } else {
32 | throw new IllegalArgumentException("illegal char at " + (i + 1) + "/" + Integer.toHexString(c) );
33 | }
34 |
35 | c = ( (c >>> 8) & 0xff) * 0xC0 + (c & 0xff);
36 |
37 | buffer.put(c, 13);
38 |
39 | i += 2;
40 | }
41 |
42 | if (i < data.length) {
43 | throw new IllegalArgumentException("illegal char at " + (i + 1) );
44 | }
45 |
46 | } catch(UnsupportedEncodingException e) {
47 | throw new RuntimeException(e.getMessage() );
48 | }
49 | }
50 |
51 | public int getLength() {
52 | try {
53 | return getData().getBytes(QRUtil.getJISEncoding() ).length / 2;
54 | } catch(UnsupportedEncodingException e) {
55 | throw new RuntimeException(e.getMessage() );
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/java/src/main/java/com/d_project/qrcode/QRMath.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | /**
4 | * QRMath
5 | * @author Kazuhiko Arase
6 | */
7 | class QRMath {
8 |
9 | private QRMath() {
10 | }
11 |
12 | private static final int[] EXP_TABLE;
13 | private static final int[] LOG_TABLE;
14 |
15 | static {
16 |
17 | EXP_TABLE = new int[256];
18 |
19 | for (int i = 0; i < 8; i++) {
20 | EXP_TABLE[i] = 1 << i;
21 | }
22 |
23 | for (int i = 8; i < 256; i++) {
24 | EXP_TABLE[i] = EXP_TABLE[i - 4]
25 | ^ EXP_TABLE[i - 5]
26 | ^ EXP_TABLE[i - 6]
27 | ^ EXP_TABLE[i - 8];
28 | }
29 |
30 | LOG_TABLE = new int[256];
31 | for (int i = 0; i < 255; i++) {
32 | LOG_TABLE[EXP_TABLE[i] ] = i;
33 | }
34 | }
35 |
36 | public static int glog(int n) {
37 |
38 | if (n < 1) {
39 | throw new ArithmeticException("log(" + n + ")");
40 | }
41 |
42 | return LOG_TABLE[n];
43 | }
44 |
45 | public static int gexp(int n) {
46 |
47 | while (n < 0) {
48 | n += 255;
49 | }
50 |
51 | while (n >= 256) {
52 | n -= 255;
53 | }
54 |
55 | return EXP_TABLE[n];
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/java/src/main/java/com/d_project/qrcode/QRNumber.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | /**
4 | * QRNumber
5 | * @author Kazuhiko Arase
6 | */
7 | class QRNumber extends QRData {
8 |
9 | public QRNumber(String data) {
10 | super(Mode.MODE_NUMBER, data);
11 | }
12 |
13 | public void write(BitBuffer buffer) {
14 |
15 | String data = getData();
16 |
17 | int i = 0;
18 |
19 | while (i + 2 < data.length() ) {
20 | int num = parseInt(data.substring(i, i + 3) );
21 | buffer.put(num, 10);
22 | i += 3;
23 | }
24 |
25 | if (i < data.length() ) {
26 | if (data.length() - i == 1) {
27 | int num = parseInt(data.substring(i, i + 1) );
28 | buffer.put(num, 4);
29 | } else if (data.length() - i == 2) {
30 | int num = parseInt(data.substring(i, i + 2) );
31 | buffer.put(num, 7);
32 | }
33 | }
34 | }
35 |
36 | public int getLength() {
37 | return getData().length();
38 | }
39 |
40 | private static int parseInt(String s) {
41 | int num = 0;
42 | for (int i = 0; i < s.length(); i++) {
43 | num = num * 10 + parseInt(s.charAt(i) );
44 | }
45 | return num;
46 | }
47 |
48 | private static int parseInt(char c) {
49 | if ('0' <= c && c <= '9') {
50 | return c - '0';
51 | }
52 | throw new IllegalArgumentException("illegal char :" + c);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/java/src/main/java/com/d_project/qrcode/QRUtil.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | import java.io.UnsupportedEncodingException;
4 |
5 | /**
6 | * QRUtil
7 | * @author Kazuhiko Arase
8 | */
9 | class QRUtil {
10 |
11 | private QRUtil() {
12 | }
13 |
14 | public static String getJISEncoding() {
15 | return "SJIS";
16 | }
17 |
18 | public static int[] getPatternPosition(int typeNumber) {
19 | return PATTERN_POSITION_TABLE[typeNumber - 1];
20 | }
21 |
22 | private static final int[][] PATTERN_POSITION_TABLE ={
23 | {},
24 | {6, 18},
25 | {6, 22},
26 | {6, 26},
27 | {6, 30},
28 | {6, 34},
29 | {6, 22, 38},
30 | {6, 24, 42},
31 | {6, 26, 46},
32 | {6, 28, 50},
33 | {6, 30, 54},
34 | {6, 32, 58},
35 | {6, 34, 62},
36 | {6, 26, 46, 66},
37 | {6, 26, 48, 70},
38 | {6, 26, 50, 74},
39 | {6, 30, 54, 78},
40 | {6, 30, 56, 82},
41 | {6, 30, 58, 86},
42 | {6, 34, 62, 90},
43 | {6, 28, 50, 72, 94},
44 | {6, 26, 50, 74, 98},
45 | {6, 30, 54, 78, 102},
46 | {6, 28, 54, 80, 106},
47 | {6, 32, 58, 84, 110},
48 | {6, 30, 58, 86, 114},
49 | {6, 34, 62, 90, 118},
50 | {6, 26, 50, 74, 98, 122},
51 | {6, 30, 54, 78, 102, 126},
52 | {6, 26, 52, 78, 104, 130},
53 | {6, 30, 56, 82, 108, 134},
54 | {6, 34, 60, 86, 112, 138},
55 | {6, 30, 58, 86, 114, 142},
56 | {6, 34, 62, 90, 118, 146},
57 | {6, 30, 54, 78, 102, 126, 150},
58 | {6, 24, 50, 76, 102, 128, 154},
59 | {6, 28, 54, 80, 106, 132, 158},
60 | {6, 32, 58, 84, 110, 136, 162},
61 | {6, 26, 54, 82, 110, 138, 166},
62 | {6, 30, 58, 86, 114, 142, 170}
63 | };
64 |
65 | private static int[][][] MAX_LENGTH = {
66 | { {41, 25, 17, 10}, {34, 20, 14, 8}, {27, 16, 11, 7}, {17, 10, 7, 4} },
67 | { {77, 47, 32, 20}, {63, 38, 26, 16}, {48, 29, 20, 12}, {34, 20, 14, 8} },
68 | { {127, 77, 53, 32}, {101, 61, 42, 26}, {77, 47, 32, 20}, {58, 35, 24, 15} },
69 | { {187, 114, 78, 48}, {149, 90, 62, 38}, {111, 67, 46, 28}, {82, 50, 34, 21} },
70 | { {255, 154, 106, 65}, {202, 122, 84, 52}, {144, 87, 60, 37}, {106, 64, 44, 27} },
71 | { {322, 195, 134, 82}, {255, 154, 106, 65}, {178, 108, 74, 45}, {139, 84, 58, 36} },
72 | { {370, 224, 154, 95}, {293, 178, 122, 75}, {207, 125, 86, 53}, {154, 93, 64, 39} },
73 | { {461, 279, 192, 118}, {365, 221, 152, 93}, {259, 157, 108, 66}, {202, 122, 84, 52} },
74 | { {552, 335, 230, 141}, {432, 262, 180, 111}, {312, 189, 130, 80}, {235, 143, 98, 60} },
75 | { {652, 395, 271, 167}, {513, 311, 213, 131}, {364, 221, 151, 93}, {288, 174, 119, 74} }
76 | };
77 |
78 | public static int getMaxLength(int typeNumber, int mode, int errorCorrectionLevel) {
79 |
80 | int t = typeNumber - 1;
81 | int e = 0;
82 | int m = 0;
83 |
84 | switch(errorCorrectionLevel) {
85 | case ErrorCorrectionLevel.L : e = 0; break;
86 | case ErrorCorrectionLevel.M : e = 1; break;
87 | case ErrorCorrectionLevel.Q : e = 2; break;
88 | case ErrorCorrectionLevel.H : e = 3; break;
89 | default :
90 | throw new IllegalArgumentException("e:" + errorCorrectionLevel);
91 | }
92 |
93 | switch(mode) {
94 | case Mode.MODE_NUMBER : m = 0; break;
95 | case Mode.MODE_ALPHA_NUM : m = 1; break;
96 | case Mode.MODE_8BIT_BYTE : m = 2; break;
97 | case Mode.MODE_KANJI : m = 3; break;
98 | default :
99 | throw new IllegalArgumentException("m:" + mode);
100 | }
101 |
102 | return MAX_LENGTH[t][e][m];
103 | }
104 |
105 |
106 | /**
107 | * エラー訂正多項式を取得する。
108 | */
109 | public static Polynomial getErrorCorrectPolynomial(int errorCorrectLength) {
110 |
111 | Polynomial a = new Polynomial(new int[]{1});
112 |
113 | for (int i = 0; i < errorCorrectLength; i++) {
114 | a = a.multiply(new Polynomial(new int[]{1, QRMath.gexp(i) }) );
115 | }
116 |
117 | return a;
118 | }
119 |
120 | /**
121 | * 指定されたパターンのマスクを取得する。
122 | */
123 | public static boolean getMask(int maskPattern, int i, int j) {
124 |
125 | switch (maskPattern) {
126 |
127 | case MaskPattern.PATTERN000 : return (i + j) % 2 == 0;
128 | case MaskPattern.PATTERN001 : return i % 2 == 0;
129 | case MaskPattern.PATTERN010 : return j % 3 == 0;
130 | case MaskPattern.PATTERN011 : return (i + j) % 3 == 0;
131 | case MaskPattern.PATTERN100 : return (i / 2 + j / 3) % 2 == 0;
132 | case MaskPattern.PATTERN101 : return (i * j) % 2 + (i * j) % 3 == 0;
133 | case MaskPattern.PATTERN110 : return ( (i * j) % 2 + (i * j) % 3) % 2 == 0;
134 | case MaskPattern.PATTERN111 : return ( (i * j) % 3 + (i + j) % 2) % 2 == 0;
135 |
136 | default :
137 | throw new IllegalArgumentException("mask:" + maskPattern);
138 | }
139 | }
140 |
141 | /**
142 | * 失点を取得する
143 | */
144 | public static int getLostPoint(QRCode qrCode) {
145 |
146 | int moduleCount = qrCode.getModuleCount();
147 |
148 | int lostPoint = 0;
149 |
150 |
151 | // LEVEL1
152 |
153 | for (int row = 0; row < moduleCount; row++) {
154 |
155 | for (int col = 0; col < moduleCount; col++) {
156 |
157 | int sameCount = 0;
158 | boolean dark = qrCode.isDark(row, col);
159 |
160 | for (int r = -1; r <= 1; r++) {
161 |
162 | if (row + r < 0 || moduleCount <= row + r) {
163 | continue;
164 | }
165 |
166 | for (int c = -1; c <= 1; c++) {
167 |
168 | if (col + c < 0 || moduleCount <= col + c) {
169 | continue;
170 | }
171 |
172 | if (r == 0 && c == 0) {
173 | continue;
174 | }
175 |
176 | if (dark == qrCode.isDark(row + r, col + c) ) {
177 | sameCount++;
178 | }
179 | }
180 | }
181 |
182 | if (sameCount > 5) {
183 | lostPoint += (3 + sameCount - 5);
184 | }
185 | }
186 | }
187 |
188 | // LEVEL2
189 |
190 | for (int row = 0; row < moduleCount - 1; row++) {
191 | for (int col = 0; col < moduleCount - 1; col++) {
192 | int count = 0;
193 | if (qrCode.isDark(row, col ) ) count++;
194 | if (qrCode.isDark(row + 1, col ) ) count++;
195 | if (qrCode.isDark(row, col + 1) ) count++;
196 | if (qrCode.isDark(row + 1, col + 1) ) count++;
197 | if (count == 0 || count == 4) {
198 | lostPoint += 3;
199 | }
200 | }
201 | }
202 |
203 | // LEVEL3
204 |
205 | for (int row = 0; row < moduleCount; row++) {
206 | for (int col = 0; col < moduleCount - 6; col++) {
207 | if (qrCode.isDark(row, col)
208 | && !qrCode.isDark(row, col + 1)
209 | && qrCode.isDark(row, col + 2)
210 | && qrCode.isDark(row, col + 3)
211 | && qrCode.isDark(row, col + 4)
212 | && !qrCode.isDark(row, col + 5)
213 | && qrCode.isDark(row, col + 6) ) {
214 | lostPoint += 40;
215 | }
216 | }
217 | }
218 |
219 | for (int col = 0; col < moduleCount; col++) {
220 | for (int row = 0; row < moduleCount - 6; row++) {
221 | if (qrCode.isDark(row, col)
222 | && !qrCode.isDark(row + 1, col)
223 | && qrCode.isDark(row + 2, col)
224 | && qrCode.isDark(row + 3, col)
225 | && qrCode.isDark(row + 4, col)
226 | && !qrCode.isDark(row + 5, col)
227 | && qrCode.isDark(row + 6, col) ) {
228 | lostPoint += 40;
229 | }
230 | }
231 | }
232 |
233 | // LEVEL4
234 |
235 | int darkCount = 0;
236 |
237 | for (int col = 0; col < moduleCount; col++) {
238 | for (int row = 0; row < moduleCount; row++) {
239 | if (qrCode.isDark(row, col) ) {
240 | darkCount++;
241 | }
242 | }
243 | }
244 |
245 | int ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
246 | lostPoint += ratio * 10;
247 |
248 | return lostPoint;
249 | }
250 |
251 | public static int getMode(String s) {
252 | if (isAlphaNum(s) ) {
253 | if (isNumber(s) ) {
254 | return Mode.MODE_NUMBER;
255 | }
256 | return Mode.MODE_ALPHA_NUM;
257 | } else if (isKanji(s) ) {
258 | return Mode.MODE_KANJI;
259 | } else {
260 | return Mode.MODE_8BIT_BYTE;
261 | }
262 | }
263 |
264 | private static boolean isNumber(String s) {
265 | for (int i = 0; i < s.length(); i++) {
266 | char c = s.charAt(i);
267 | if (!('0' <= c && c <= '9') ) {
268 | return false;
269 | }
270 | }
271 | return true;
272 | }
273 |
274 | private static boolean isAlphaNum(String s) {
275 | for (int i = 0; i < s.length(); i++) {
276 | char c = s.charAt(i);
277 | if (!('0' <= c && c <= '9') && !('A' <= c && c <= 'Z') && " $%*+-./:".indexOf(c) == -1) {
278 | return false;
279 | }
280 | }
281 | return true;
282 | }
283 |
284 | private static boolean isKanji(String s) {
285 |
286 | try {
287 |
288 | byte[] data = s.getBytes(QRUtil.getJISEncoding() );
289 |
290 | int i = 0;
291 |
292 | while (i + 1 < data.length) {
293 |
294 | int c = ( (0xff & data[i]) << 8) | (0xff & data[i + 1]);
295 |
296 | if (!(0x8140 <= c && c <= 0x9FFC) && !(0xE040 <= c && c <= 0xEBBF) ) {
297 | return false;
298 | }
299 |
300 | i += 2;
301 | }
302 |
303 | if (i < data.length) {
304 | return false;
305 | }
306 |
307 | return true;
308 |
309 | } catch(UnsupportedEncodingException e) {
310 | throw new RuntimeException(e.getMessage() );
311 | }
312 | }
313 |
314 | private static final int G15 = (1 << 10) | (1 << 8) | (1 << 5)
315 | | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
316 |
317 | private static final int G18 = (1 << 12) | (1 << 11) | (1 << 10)
318 | | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);
319 |
320 | private static final int G15_MASK = (1 << 14) | (1 << 12) | (1 << 10)
321 | | (1 << 4) | (1 << 1);
322 |
323 | public static int getBCHTypeInfo(int data) {
324 | int d = data << 10;
325 | while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {
326 | d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) );
327 | }
328 | return ( (data << 10) | d) ^ G15_MASK;
329 | }
330 |
331 | public static int getBCHTypeNumber(int data) {
332 | int d = data << 12;
333 | while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {
334 | d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) );
335 | }
336 | return (data << 12) | d;
337 | }
338 |
339 | private static int getBCHDigit(int data) {
340 |
341 | int digit = 0;
342 |
343 | while (data != 0) {
344 | digit++;
345 | data >>>= 1;
346 | }
347 |
348 | return digit;
349 |
350 | }
351 | }
352 |
--------------------------------------------------------------------------------
/java/src/main/java/com/d_project/qrcode/RSBlock.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * RSBlock
8 | * @author Kazuhiko Arase
9 | */
10 | class RSBlock {
11 |
12 | private static final int[][] RS_BLOCK_TABLE = {
13 |
14 | // L
15 | // M
16 | // Q
17 | // H
18 |
19 | // 1
20 | {1, 26, 19},
21 | {1, 26, 16},
22 | {1, 26, 13},
23 | {1, 26, 9},
24 |
25 | // 2
26 | {1, 44, 34},
27 | {1, 44, 28},
28 | {1, 44, 22},
29 | {1, 44, 16},
30 |
31 | // 3
32 | {1, 70, 55},
33 | {1, 70, 44},
34 | {2, 35, 17},
35 | {2, 35, 13},
36 |
37 | // 4
38 | {1, 100, 80},
39 | {2, 50, 32},
40 | {2, 50, 24},
41 | {4, 25, 9},
42 |
43 | // 5
44 | {1, 134, 108},
45 | {2, 67, 43},
46 | {2, 33, 15, 2, 34, 16},
47 | {2, 33, 11, 2, 34, 12},
48 |
49 | // 6
50 | {2, 86, 68},
51 | {4, 43, 27},
52 | {4, 43, 19},
53 | {4, 43, 15},
54 |
55 | // 7
56 | {2, 98, 78},
57 | {4, 49, 31},
58 | {2, 32, 14, 4, 33, 15},
59 | {4, 39, 13, 1, 40, 14},
60 |
61 | // 8
62 | {2, 121, 97},
63 | {2, 60, 38, 2, 61, 39},
64 | {4, 40, 18, 2, 41, 19},
65 | {4, 40, 14, 2, 41, 15},
66 |
67 | // 9
68 | {2, 146, 116},
69 | {3, 58, 36, 2, 59, 37},
70 | {4, 36, 16, 4, 37, 17},
71 | {4, 36, 12, 4, 37, 13},
72 |
73 | // 10
74 | {2, 86, 68, 2, 87, 69},
75 | {4, 69, 43, 1, 70, 44},
76 | {6, 43, 19, 2, 44, 20},
77 | {6, 43, 15, 2, 44, 16},
78 |
79 | // 11
80 | {4, 101, 81},
81 | {1, 80, 50, 4, 81, 51},
82 | {4, 50, 22, 4, 51, 23},
83 | {3, 36, 12, 8, 37, 13},
84 |
85 | // 12
86 | {2, 116, 92, 2, 117, 93},
87 | {6, 58, 36, 2, 59, 37},
88 | {4, 46, 20, 6, 47, 21},
89 | {7, 42, 14, 4, 43, 15},
90 |
91 | // 13
92 | {4, 133, 107},
93 | {8, 59, 37, 1, 60, 38},
94 | {8, 44, 20, 4, 45, 21},
95 | {12, 33, 11, 4, 34, 12},
96 |
97 | // 14
98 | {3, 145, 115, 1, 146, 116},
99 | {4, 64, 40, 5, 65, 41},
100 | {11, 36, 16, 5, 37, 17},
101 | {11, 36, 12, 5, 37, 13},
102 |
103 | // 15
104 | {5, 109, 87, 1, 110, 88},
105 | {5, 65, 41, 5, 66, 42},
106 | {5, 54, 24, 7, 55, 25},
107 | {11, 36, 12, 7, 37, 13},
108 |
109 | // 16
110 | {5, 122, 98, 1, 123, 99},
111 | {7, 73, 45, 3, 74, 46},
112 | {15, 43, 19, 2, 44, 20},
113 | {3, 45, 15, 13, 46, 16},
114 |
115 | // 17
116 | {1, 135, 107, 5, 136, 108},
117 | {10, 74, 46, 1, 75, 47},
118 | {1, 50, 22, 15, 51, 23},
119 | {2, 42, 14, 17, 43, 15},
120 |
121 | // 18
122 | {5, 150, 120, 1, 151, 121},
123 | {9, 69, 43, 4, 70, 44},
124 | {17, 50, 22, 1, 51, 23},
125 | {2, 42, 14, 19, 43, 15},
126 |
127 | // 19
128 | {3, 141, 113, 4, 142, 114},
129 | {3, 70, 44, 11, 71, 45},
130 | {17, 47, 21, 4, 48, 22},
131 | {9, 39, 13, 16, 40, 14},
132 |
133 | // 20
134 | {3, 135, 107, 5, 136, 108},
135 | {3, 67, 41, 13, 68, 42},
136 | {15, 54, 24, 5, 55, 25},
137 | {15, 43, 15, 10, 44, 16},
138 |
139 | // 21
140 | {4, 144, 116, 4, 145, 117},
141 | {17, 68, 42},
142 | {17, 50, 22, 6, 51, 23},
143 | {19, 46, 16, 6, 47, 17},
144 |
145 | // 22
146 | {2, 139, 111, 7, 140, 112},
147 | {17, 74, 46},
148 | {7, 54, 24, 16, 55, 25},
149 | {34, 37, 13},
150 |
151 | // 23
152 | {4, 151, 121, 5, 152, 122},
153 | {4, 75, 47, 14, 76, 48},
154 | {11, 54, 24, 14, 55, 25},
155 | {16, 45, 15, 14, 46, 16},
156 |
157 | // 24
158 | {6, 147, 117, 4, 148, 118},
159 | {6, 73, 45, 14, 74, 46},
160 | {11, 54, 24, 16, 55, 25},
161 | {30, 46, 16, 2, 47, 17},
162 |
163 | // 25
164 | {8, 132, 106, 4, 133, 107},
165 | {8, 75, 47, 13, 76, 48},
166 | {7, 54, 24, 22, 55, 25},
167 | {22, 45, 15, 13, 46, 16},
168 |
169 | // 26
170 | {10, 142, 114, 2, 143, 115},
171 | {19, 74, 46, 4, 75, 47},
172 | {28, 50, 22, 6, 51, 23},
173 | {33, 46, 16, 4, 47, 17},
174 |
175 | // 27
176 | {8, 152, 122, 4, 153, 123},
177 | {22, 73, 45, 3, 74, 46},
178 | {8, 53, 23, 26, 54, 24},
179 | {12, 45, 15, 28, 46, 16},
180 |
181 | // 28
182 | {3, 147, 117, 10, 148, 118},
183 | {3, 73, 45, 23, 74, 46},
184 | {4, 54, 24, 31, 55, 25},
185 | {11, 45, 15, 31, 46, 16},
186 |
187 | // 29
188 | {7, 146, 116, 7, 147, 117},
189 | {21, 73, 45, 7, 74, 46},
190 | {1, 53, 23, 37, 54, 24},
191 | {19, 45, 15, 26, 46, 16},
192 |
193 | // 30
194 | {5, 145, 115, 10, 146, 116},
195 | {19, 75, 47, 10, 76, 48},
196 | {15, 54, 24, 25, 55, 25},
197 | {23, 45, 15, 25, 46, 16},
198 |
199 | // 31
200 | {13, 145, 115, 3, 146, 116},
201 | {2, 74, 46, 29, 75, 47},
202 | {42, 54, 24, 1, 55, 25},
203 | {23, 45, 15, 28, 46, 16},
204 |
205 | // 32
206 | {17, 145, 115},
207 | {10, 74, 46, 23, 75, 47},
208 | {10, 54, 24, 35, 55, 25},
209 | {19, 45, 15, 35, 46, 16},
210 |
211 | // 33
212 | {17, 145, 115, 1, 146, 116},
213 | {14, 74, 46, 21, 75, 47},
214 | {29, 54, 24, 19, 55, 25},
215 | {11, 45, 15, 46, 46, 16},
216 |
217 | // 34
218 | {13, 145, 115, 6, 146, 116},
219 | {14, 74, 46, 23, 75, 47},
220 | {44, 54, 24, 7, 55, 25},
221 | {59, 46, 16, 1, 47, 17},
222 |
223 | // 35
224 | {12, 151, 121, 7, 152, 122},
225 | {12, 75, 47, 26, 76, 48},
226 | {39, 54, 24, 14, 55, 25},
227 | {22, 45, 15, 41, 46, 16},
228 |
229 | // 36
230 | {6, 151, 121, 14, 152, 122},
231 | {6, 75, 47, 34, 76, 48},
232 | {46, 54, 24, 10, 55, 25},
233 | {2, 45, 15, 64, 46, 16},
234 |
235 | // 37
236 | {17, 152, 122, 4, 153, 123},
237 | {29, 74, 46, 14, 75, 47},
238 | {49, 54, 24, 10, 55, 25},
239 | {24, 45, 15, 46, 46, 16},
240 |
241 | // 38
242 | {4, 152, 122, 18, 153, 123},
243 | {13, 74, 46, 32, 75, 47},
244 | {48, 54, 24, 14, 55, 25},
245 | {42, 45, 15, 32, 46, 16},
246 |
247 | // 39
248 | {20, 147, 117, 4, 148, 118},
249 | {40, 75, 47, 7, 76, 48},
250 | {43, 54, 24, 22, 55, 25},
251 | {10, 45, 15, 67, 46, 16},
252 |
253 | // 40
254 | {19, 148, 118, 6, 149, 119},
255 | {18, 75, 47, 31, 76, 48},
256 | {34, 54, 24, 34, 55, 25},
257 | {20, 45, 15, 61, 46, 16}
258 | };
259 |
260 | private int totalCount;
261 | private int dataCount;
262 |
263 | private RSBlock(int totalCount, int dataCount) {
264 | this.totalCount = totalCount;
265 | this.dataCount = dataCount;
266 | }
267 |
268 | public final int getDataCount() {
269 | return dataCount;
270 | }
271 |
272 | public final int getTotalCount() {
273 | return totalCount;
274 | }
275 |
276 | public static RSBlock[] getRSBlocks(int typeNumber, int errorCorrectionLevel) {
277 |
278 | int[] rsBlock = getRsBlockTable(typeNumber, errorCorrectionLevel);
279 | int length = rsBlock.length / 3;
280 |
281 |
282 | List list = new ArrayList();
283 |
284 | for (int i = 0; i < length; i++) {
285 |
286 | int count = rsBlock[i * 3 + 0];
287 | int totalCount = rsBlock[i * 3 + 1];
288 | int dataCount = rsBlock[i * 3 + 2];
289 |
290 | for (int j = 0; j < count; j++) {
291 | list.add(new RSBlock(totalCount, dataCount) );
292 | }
293 | }
294 |
295 | return list.toArray(new RSBlock[list.size() ]);
296 | }
297 |
298 | private static int[] getRsBlockTable(int typeNumber, int errorCorrectionLevel) {
299 |
300 | try {
301 |
302 | switch(errorCorrectionLevel) {
303 | case ErrorCorrectionLevel.L :
304 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
305 | case ErrorCorrectionLevel.M :
306 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
307 | case ErrorCorrectionLevel.Q :
308 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
309 | case ErrorCorrectionLevel.H :
310 | return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
311 | default :
312 | break;
313 | }
314 |
315 | } catch(Exception e) {
316 | }
317 |
318 | throw new IllegalArgumentException("tn:" + typeNumber + "/ecl:" + errorCorrectionLevel);
319 | }
320 | }
321 |
--------------------------------------------------------------------------------
/java/src/main/java/com/d_project/qrcode/web/GIFImage.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode.web;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.IOException;
5 | import java.io.OutputStream;
6 | import java.util.HashMap;
7 | import java.util.Map;
8 |
9 | /**
10 | * GIFイメージ(B/W)
11 | * @author Kazuhiko Arase
12 | */
13 | class GIFImage {
14 |
15 | private int width;
16 | private int height;
17 | private int[] data;
18 |
19 | public GIFImage(int width, int height) {
20 | this.width = width;
21 | this.height = height;
22 | this.data = new int[width * height];
23 | }
24 |
25 | public void setPixel(int x, int y, int pixel) {
26 | if (x < 0 || width <= x) throw new IllegalArgumentException();
27 | if (y < 0 || height <= y) throw new IllegalArgumentException();
28 | data[y * width + x] = pixel;
29 | }
30 |
31 | public int getPixel(int x, int y) {
32 | if (x < 0 || width <= x) throw new IllegalArgumentException();
33 | if (y < 0 || height <= y) throw new IllegalArgumentException();
34 | return data[y * width + x];
35 | }
36 |
37 | public void write(OutputStream out) throws IOException {
38 |
39 | //---------------------------------
40 | // GIF Signature
41 |
42 | out.write("GIF87a".getBytes("ISO-8859-1") );
43 |
44 | //---------------------------------
45 | // Screen Descriptor
46 |
47 | write(out, width);
48 | write(out, height);
49 |
50 | out.write(0x80); // 2bit
51 | out.write(0);
52 | out.write(0);
53 |
54 | //---------------------------------
55 | // Global Color Map
56 |
57 | // black
58 | out.write(0x00);
59 | out.write(0x00);
60 | out.write(0x00);
61 |
62 | // white
63 | out.write(0xff);
64 | out.write(0xff);
65 | out.write(0xff);
66 |
67 | //---------------------------------
68 | // Image Descriptor
69 |
70 | out.write(',');
71 | write(out, 0);
72 | write(out, 0);
73 | write(out, width);
74 | write(out, height);
75 | out.write(0);
76 |
77 | //---------------------------------
78 | // Local Color Map
79 |
80 | //---------------------------------
81 | // Raster Data
82 |
83 | int lzwMinCodeSize = 2;
84 | byte[] raster = getLZWRaster(lzwMinCodeSize);
85 |
86 | out.write(lzwMinCodeSize);
87 |
88 | int offset = 0;
89 |
90 | while (raster.length - offset > 255) {
91 | out.write(255);
92 | out.write(raster, offset, 255);
93 | offset += 255;
94 | }
95 |
96 | out.write(raster.length - offset);
97 | out.write(raster, offset, raster.length - offset);
98 | out.write(0x00);
99 |
100 | //---------------------------------
101 | // GIF Terminator
102 | out.write(';');
103 |
104 | }
105 |
106 | private byte[] getLZWRaster(int lzwMinCodeSize) throws IOException {
107 |
108 | int clearCode = 1 << lzwMinCodeSize;
109 | int endCode = (1 << lzwMinCodeSize) + 1;
110 | int bitLength = lzwMinCodeSize + 1;
111 |
112 | // Setup LZWTable
113 | LZWTable table = new LZWTable();
114 |
115 | for (int i = 0; i < clearCode; i++) {
116 | table.add(String.valueOf( (char)i) );
117 | }
118 | table.add(String.valueOf( (char)clearCode) );
119 | table.add(String.valueOf( (char)endCode) );
120 |
121 |
122 | ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
123 | BitOutputStream bitOut = new BitOutputStream(byteOut);
124 |
125 | try {
126 |
127 | // clear code
128 | bitOut.write(clearCode, bitLength);
129 |
130 | int dataIndex = 0;
131 | String s = String.valueOf( (char)data[dataIndex++]);
132 |
133 | while (dataIndex < data.length) {
134 |
135 | char c = (char)data[dataIndex++];
136 |
137 | if (table.contains(s + c) ) {
138 |
139 | s = s + c;
140 |
141 | } else {
142 |
143 | bitOut.write(table.indexOf(s), bitLength);
144 |
145 | if (table.size() < 0xfff) {
146 |
147 | if (table.size() == (1 << bitLength) ) {
148 | bitLength++;
149 | }
150 |
151 | table.add(s + c);
152 | }
153 |
154 | s = String.valueOf(c);
155 | }
156 | }
157 |
158 | bitOut.write(table.indexOf(s), bitLength);
159 |
160 | // end code
161 | bitOut.write(endCode, bitLength);
162 |
163 | } finally {
164 | bitOut.close();
165 | }
166 |
167 | return byteOut.toByteArray();
168 | }
169 |
170 | private static void write(OutputStream out, int i) throws IOException {
171 | out.write(i & 0xff);
172 | out.write( (i >>> 8) & 0xff);
173 | }
174 |
175 | private static class LZWTable {
176 |
177 | private Map map;
178 |
179 | public LZWTable() {
180 | map = new HashMap();
181 | }
182 |
183 | public void add(String key) {
184 | if (contains(key) ) {
185 | throw new IllegalArgumentException("dup key:" + key);
186 | }
187 | map.put(key, map.size() );
188 | }
189 |
190 | public int size() {
191 | return map.size();
192 | }
193 |
194 | public int indexOf(String key) {
195 | return ( (Integer)map.get(key) ).intValue();
196 | }
197 |
198 | public boolean contains(String key) {
199 | return map.containsKey(key);
200 | }
201 |
202 | }
203 |
204 | private static class BitOutputStream {
205 |
206 | private OutputStream out;
207 | private int bitLength;
208 | private int bitBuffer;
209 |
210 | public BitOutputStream(OutputStream out) {
211 | this.out = out;
212 | this.bitLength = 0;
213 | }
214 |
215 | public void write(int data, int length) throws IOException{
216 |
217 | if ( (data >>> length) != 0) {
218 | throw new IOException("length over");
219 | }
220 |
221 | while (bitLength + length >= 8) {
222 | out.write(0xff & ( (data << bitLength) | bitBuffer) );
223 | length -= (8 - bitLength);
224 | data >>>= (8 - bitLength);
225 | bitBuffer = 0;
226 | bitLength = 0;
227 | }
228 |
229 | bitBuffer = (data << bitLength) | bitBuffer;
230 | bitLength = bitLength + length;
231 | }
232 |
233 | public void flush() throws IOException {
234 | if (bitLength > 0) {
235 | out.write(bitBuffer);
236 | }
237 | out.flush();
238 | }
239 |
240 | public void close() throws IOException {
241 | flush();
242 | out.close();
243 | }
244 |
245 | }
246 |
247 | }
248 |
--------------------------------------------------------------------------------
/java/src/main/java/com/d_project/qrcode/web/QRCodeServlet.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode.web;
2 |
3 | import java.awt.image.BufferedImage;
4 | import java.io.BufferedOutputStream;
5 | import java.io.IOException;
6 | import java.io.OutputStream;
7 | import java.io.OutputStreamWriter;
8 | import java.io.PrintWriter;
9 |
10 | import javax.imageio.ImageIO;
11 | import javax.servlet.ServletConfig;
12 | import javax.servlet.ServletException;
13 | import javax.servlet.http.HttpServlet;
14 | import javax.servlet.http.HttpServletRequest;
15 | import javax.servlet.http.HttpServletResponse;
16 |
17 | import com.d_project.qrcode.ErrorCorrectionLevel;
18 | import com.d_project.qrcode.QRCode;
19 |
20 | /**
21 | * QRコードサーブレット.
22 | *
QRコードのモノクロGIF画像を応答するサーブレットです。
23 | *
[パラメータ]
24 | *
o : 出力形式 (text/plain, image/gif, image/jpeg, image/png のいずれか, 省略した場合は image/gif)
25 | *
t : 型番 (0:自動, 1~10, 省略した場合は 0)
26 | *
e : 誤り訂正レベル (L, Q, M, H のいずれか, 省略した場合は H)
27 | *
d : テキストデータ (文字列)
28 | *
m : マージン (0~32, 省略した場合は 0)
29 | *
s : セルサイズ (1~4, 省略した場合は 1)
30 | * @author Kazuhiko Arase
31 | * @see com.d_project.qrcode.Mode
32 | * @see com.d_project.qrcode.ErrorCorrectionLevel
33 | */
34 | @SuppressWarnings("serial")
35 | public class QRCodeServlet extends HttpServlet {
36 |
37 | private String defaultCharacterEncoding;
38 |
39 | /**
40 | * コンストラクタ
41 | */
42 | public QRCodeServlet() {
43 | }
44 |
45 | public void init(ServletConfig config) throws ServletException {
46 |
47 | super.init(config);
48 |
49 | defaultCharacterEncoding = getServletConfig().getInitParameter("default-character-encoding");
50 | }
51 |
52 | public void doGet(HttpServletRequest request, HttpServletResponse response)
53 | throws ServletException, IOException {
54 |
55 | String data = getParameter(request, "d", "qrcode");
56 |
57 | if (defaultCharacterEncoding != null) {
58 | data = new String(data.getBytes("ISO-8859-1"), defaultCharacterEncoding);
59 | }
60 |
61 | String output = getParameter(request, "o", "image/gif");
62 |
63 | int typeNumber = getIntParameter(request, "t", 0);
64 | if (typeNumber < 0 || 10 < typeNumber) {
65 | throw new IllegalArgumentException("illegal type number : " + typeNumber);
66 | }
67 |
68 | int margin = getIntParameter(request, "m", 2);
69 | if (margin < 0 || 32 < margin) {
70 | throw new IllegalArgumentException("illegal margin : " + margin);
71 | }
72 |
73 | int cellSize = getIntParameter(request, "s", 1);
74 | if (cellSize < 1 || 4 < cellSize) {
75 | throw new IllegalArgumentException("illegal cell size : " + cellSize);
76 | }
77 |
78 | int errorCorrectionLevel = parseErrorCorrectionLevel(getParameter(request, "e", "H") );
79 |
80 | QRCode qrcode = getQRCode(data, typeNumber, errorCorrectionLevel);
81 |
82 | if ("text/plain".equals(output) ) {
83 |
84 | response.setContentType("text/plain");
85 |
86 | PrintWriter out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(), "ISO-8859-1") );
87 |
88 | try {
89 | for (int row = 0; row < qrcode.getModuleCount(); row++) {
90 | for (int col = 0; col < qrcode.getModuleCount(); col++) {
91 | out.print(qrcode.isDark(row, col)? "1" : "0");
92 | }
93 | out.print("\r\n");
94 | }
95 | } finally {
96 | out.close();
97 | }
98 |
99 | } else if ("image/jpeg".equals(output) ) {
100 |
101 | BufferedImage image = qrcode.createImage(cellSize, margin);
102 |
103 | response.setContentType("image/jpeg");
104 |
105 | OutputStream out = new BufferedOutputStream(response.getOutputStream() );
106 |
107 | try {
108 | ImageIO.write(image, "jpeg", out);
109 | } finally {
110 | out.close();
111 | }
112 |
113 | } else if ("image/png".equals(output) ) {
114 |
115 | BufferedImage image = qrcode.createImage(cellSize, margin);
116 |
117 | response.setContentType("image/png");
118 |
119 | OutputStream out = new BufferedOutputStream(response.getOutputStream() );
120 |
121 | try {
122 | ImageIO.write(image, "png", out);
123 | } finally {
124 | out.close();
125 | }
126 |
127 | } else if ("image/gif".equals(output) ) {
128 |
129 | GIFImage image = createGIFImage(qrcode, cellSize, margin);
130 |
131 | response.setContentType("image/gif");
132 |
133 | OutputStream out = new BufferedOutputStream(response.getOutputStream() );
134 |
135 | try {
136 | image.write(out);
137 | } finally {
138 | out.close();
139 | }
140 |
141 | } else {
142 | throw new IllegalArgumentException("illegal output type : " + output);
143 | }
144 | }
145 |
146 | private static String getParameter(HttpServletRequest request, String name, String defaultValue) {
147 | String value = request.getParameter(name);
148 | return (value != null)? value : defaultValue;
149 | }
150 |
151 | private static int getIntParameter(HttpServletRequest request, String name, int defaultValue) {
152 | String value = request.getParameter(name);
153 | return (value != null)? Integer.parseInt(value) : defaultValue;
154 | }
155 |
156 | private static QRCode getQRCode(String text, int typeNumber, int errorCorrectionLevel) {
157 |
158 | if (typeNumber == 0) {
159 |
160 | return QRCode.getMinimumQRCode(text, errorCorrectionLevel);
161 |
162 | } else {
163 |
164 | QRCode qr = new QRCode();
165 | qr.setTypeNumber(typeNumber);
166 | qr.setErrorCorrectionLevel(errorCorrectionLevel);
167 | qr.addData(text);
168 | qr.make();
169 |
170 | return qr;
171 |
172 | }
173 | }
174 |
175 | private static int parseErrorCorrectionLevel(String ecl) {
176 |
177 | if ("L".equals(ecl) ) {
178 | return ErrorCorrectionLevel.L;
179 | } else if ("Q".equals(ecl) ) {
180 | return ErrorCorrectionLevel.Q;
181 | } else if ("M".equals(ecl) ) {
182 | return ErrorCorrectionLevel.M;
183 | } else if ("H".equals(ecl) ) {
184 | return ErrorCorrectionLevel.H;
185 | } else {
186 | throw new IllegalArgumentException("invalid error correct level : " + ecl);
187 | }
188 |
189 | }
190 |
191 | /**
192 | * GIFイメージを取得する。
193 | * @param cellSize セルのサイズ(pixel)
194 | * @param margin 余白(pixel)
195 | */
196 | private static GIFImage createGIFImage(QRCode qrcode, int cellSize, int margin) throws IOException {
197 |
198 | int imageSize = qrcode.getModuleCount() * cellSize + margin * 2;
199 |
200 | GIFImage image = new GIFImage(imageSize, imageSize);
201 |
202 | for (int y = 0; y < imageSize; y++) {
203 |
204 | for (int x = 0; x < imageSize; x++) {
205 |
206 | if (margin <= x && x < imageSize - margin
207 | && margin <= y && y < imageSize - margin) {
208 |
209 | int col = (x - margin) / cellSize;
210 | int row = (y - margin) / cellSize;
211 |
212 | if (qrcode.isDark(row, col) ) {
213 | image.setPixel(x, y, 0);
214 | } else {
215 | image.setPixel(x, y, 1);
216 | }
217 |
218 | } else {
219 | image.setPixel(x, y, 1);
220 | }
221 | }
222 | }
223 |
224 | return image;
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/java/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 | qrcode
10 | com.d_project.qrcode.web.QRCodeServlet
11 |
12 | default-character-encoding
13 | Utf-8
14 |
15 |
16 |
17 |
18 | qrcode
19 | /qrcode
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/java/src/main/webapp/form.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html; charset=Utf-8" %>
2 |
3 |
4 |
11 |
12 |
13 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/java/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 | <%@ page contentType="text/html; charset=Utf-8" %>
2 |
3 |
4 |
5 | QRCode for Java
6 |
7 |
8 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/java/src/test/java/com/d_project/qrcode/BitBufferTest.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class BitBufferTest {
7 |
8 | @Test
9 | public void test1() {
10 | BitBuffer bb = new BitBuffer();
11 | QRData qd = new QR8BitByte("534TEST!!!あ");
12 | qd.write(bb);
13 |
14 | Assert.assertEquals(96, bb.getLengthInBits() );
15 | }
16 |
17 | @Test
18 | public void test2() {
19 | BitBuffer bb = new BitBuffer();
20 | QRData qd = new QRAlphaNum("534TEST $%*+-./:");
21 | qd.write(bb);
22 |
23 | Assert.assertEquals(88, bb.getLengthInBits() );
24 | }
25 |
26 | @Test
27 | public void test3() {
28 | BitBuffer bb = new BitBuffer();
29 | QRData qd = new QRKanji("あいうえお");
30 | qd.write(bb);
31 |
32 | Assert.assertEquals(65, bb.getLengthInBits() );
33 | }
34 |
35 | @Test
36 | public void test4() {
37 | BitBuffer bb = new BitBuffer();
38 | QRData qd = new QRNumber("0123456789");
39 | qd.write(bb);
40 |
41 | Assert.assertEquals(34, bb.getLengthInBits() );
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/java/src/test/java/com/d_project/qrcode/PolynomialTest.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class PolynomialTest {
7 |
8 | @Test
9 | public void test1() {
10 |
11 | int[] rs = new int[] {0, 43, 139, 206, 78, 43, 239, 123, 206, 214, 147, 24, 99, 150, 39, 243, 163, 136};
12 | for (int i = 0; i < rs.length; i++) {
13 | rs[i] = QRMath.gexp(rs[i]);
14 | }
15 | int[] data = new int[]{32,65,205,69,41,220,46,128,236};
16 |
17 | Polynomial e = new Polynomial(rs);
18 | Polynomial e2 = new Polynomial(data, e.getLength() - 1);
19 |
20 | assertEquals(new int[]{32,65,205,69,41,220,46,128,236,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, e2);
21 | assertEquals(new int[]{1,119,66,83,120,119,22,197,83,249,41,143,134,85,53,125,99,79}, e);
22 | assertEquals(new int[]{42,159,74,221,244,169,239,150,138,70,237,85,224,96,74,219,61}, e2.mod(e) );
23 | }
24 |
25 | @Test
26 | public void test2() {
27 |
28 | Polynomial a = new Polynomial(new int[]{1}, 0);
29 | for (int i = 0; i < 7; i++) {
30 | a = a.multiply(new Polynomial(new int[]{1, QRMath.gexp(i) }, 0) );
31 | }
32 |
33 | int[] log = {0,87,229,146,149,238,102,21};
34 | Assert.assertEquals(log.length, a.getLength() );
35 | for (int i = 0; i < a.getLength(); i++) {
36 | Assert.assertEquals(log[i], QRMath.glog(a.get(i) ) );
37 | }
38 | }
39 |
40 | protected void assertEquals(int[] num, Polynomial p) {
41 | Assert.assertEquals(num.length, p.getLength() );
42 | for (int i = 0; i < num.length; i++) {
43 | Assert.assertEquals(num[i], p.get(i) );
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/java/src/test/java/com/d_project/qrcode/QRCodeTest.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class QRCodeTest {
7 |
8 | @Test
9 | public void test1() {
10 | QRNumber data = new QRNumber("0123");
11 | byte[] act = QRCode.createData(1, ErrorCorrectionLevel.H, new QRData[]{data} );
12 | byte[] exp = new byte[]{16,16,12,48,-20,17,-20,17,-20,-50,-20,-24,66,-27,44,-31,-124,-111,13,-69,-37,15,-16,36,-69,104};
13 | assertEquals(exp, act);
14 | }
15 |
16 | @Test
17 | public void test2() {
18 | QRAlphaNum data = new QRAlphaNum("AB01");
19 | byte[] act = QRCode.createData(1, ErrorCorrectionLevel.H, new QRData[]{data} );
20 | byte[] exp = new byte[]{32,33,-51,0,32,-20,17,-20,17,105,-125,-85,106,65,-91,54,-123,-112,-11,-73,21,-13,-106,-89,114,-25};
21 | assertEquals(exp, act);
22 | }
23 |
24 | @Test
25 | public void test3() {
26 | QRKanji data = new QRKanji("漢字");
27 | byte[] act = QRCode.createData(1, ErrorCorrectionLevel.H, new QRData[]{data} );
28 | byte[] exp = new byte[]{-128,35,-97,-88,104,0,-20,17,-20,-11,-82,108,-126,119,-6,118,-128,99,-41,-105,117,-68,-107,-120,47,-5};
29 | assertEquals(exp, act);
30 | }
31 |
32 | @Test
33 | public void test4() {
34 | QR8BitByte data = new QR8BitByte("ab01");
35 | byte[] act = QRCode.createData(1, ErrorCorrectionLevel.H, new QRData[]{data} );
36 | byte[] exp = new byte[]{64,70,22,35,3,16,-20,17,-20,91,-25,80,48,-87,54,40,-83,84,-117,33,87,54,-57,50,-84,49};
37 | assertEquals(exp, act);
38 | }
39 |
40 | protected void assertEquals(byte[] expected, byte[] actual) {
41 | Assert.assertEquals(expected.length, actual.length);
42 | for (int i = 0; i < expected.length; i++) {
43 | Assert.assertEquals(expected[i], actual[i]);
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/java/src/test/java/com/d_project/qrcode/web/GIFImageTest.java:
--------------------------------------------------------------------------------
1 | package com.d_project.qrcode.web;
2 |
3 | import java.io.ByteArrayOutputStream;
4 |
5 | import org.junit.Test;
6 |
7 | public class GIFImageTest {
8 |
9 | @Test
10 | public void test() throws Exception {
11 |
12 | GIFImage g = new GIFImage(2, 2);
13 | g.setPixel(0, 0, 1);
14 | g.setPixel(0, 1, 0);
15 | g.setPixel(1, 0, 0);
16 | g.setPixel(1, 1, 1);
17 |
18 | ByteArrayOutputStream b = new ByteArrayOutputStream();
19 | g.write(b);
20 | byte[] raw = b.toByteArray();
21 | for (int i = 0; i < raw.length; i++) {
22 | if (i > 0) {
23 | System.out.print(",");
24 | }
25 | System.out.print(raw[i] & 0xff);
26 | }
27 | System.out.println();
28 | }
29 | }
--------------------------------------------------------------------------------
/js/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | *.tgz
3 |
--------------------------------------------------------------------------------
/js/.npmignore:
--------------------------------------------------------------------------------
1 | ts-test
2 | misc
3 | demo
4 | sample.*
5 | *.tgz
6 |
--------------------------------------------------------------------------------
/js/README.md:
--------------------------------------------------------------------------------
1 | QR Code Generator
2 | ===
3 |
4 | ## Getting Started
5 |
6 | 1. Include qrcode.js in your html.
7 | 2. Prepare a place holder.
8 | 3. Generate QR and render it.
9 |
10 | ```html
11 |
12 | ```
13 | ```html
14 |
15 | ```
16 | ```javascript
17 | var typeNumber = 4;
18 | var errorCorrectionLevel = 'L';
19 | var qr = qrcode(typeNumber, errorCorrectionLevel);
20 | qr.addData('Hi!');
21 | qr.make();
22 | document.getElementById('placeHolder').innerHTML = qr.createImgTag();
23 | ```
24 | ## API Documentation
25 |
26 | ### QRCodeFactory
27 |
28 | #### qrcode(typeNumber, errorCorrectionLevel) => QRCode
29 | Create a QRCode Object.
30 |
31 | | Param | Type | Description |
32 | | ---------------------| ------------------- | ---------------------------------------------- |
33 | | typeNumber | number
| Type number (1 ~ 40), or 0 for auto detection. |
34 | | errorCorrectionLevel | string
| Error correction level ('L', 'M', 'Q', 'H') |
35 |
36 | #### qrcode.stringToBytes(s) : number[]
37 | Encodes a string into an array of number(byte) using any charset.
38 | This function is used by internal.
39 | Overwrite this function to encode using a multibyte charset.
40 |
41 | | Param | Type | Description |
42 | | ------ | ------------------- | ---------------- |
43 | | s | string
| string to encode |
44 |
45 | ### QRCode
46 |
47 | #### addData(data, mode) => void
48 | Add a data to encode.
49 |
50 | | Param | Type | Description |
51 | | ------ | ------------------- | ---------------------------------------------------------- |
52 | | data | string
| string to encode |
53 | | mode | string
| Mode ('Numeric', 'Alphanumeric', 'Byte'(default), 'Kanji') |
54 |
55 | #### make() => void
56 | Make a QR Code.
57 |
58 | #### getModuleCount() => number
59 | The number of modules(cells) for each orientation.
60 | _[Note] call make() before this function._
61 |
62 | #### isDark(row, col) => boolean
63 | The module at row and col is dark or not.
64 | _[Note] call make() before this function._
65 |
66 | | Param | Type | Description |
67 | | ----- | ------------------- | ------------------- |
68 | | row | number
| 0 ~ moduleCount - 1 |
69 | | col | number
| 0 ~ moduleCount - 1 |
70 |
71 | #### createDataURL(cellSize, margin) => string
72 | #### createImgTag(cellSize, margin, alt) => string
73 | #### createSvgTag(cellSize, margin) => string
74 | #### createTableTag(cellSize, margin) => string
75 | #### createASCII(cellSize, margin) => string
76 | Helper functions for HTML.
77 | _[Note] call make() before these functions._
78 |
79 | | Param | Type | Description |
80 | | -------- | ------------------- | --------------------- |
81 | | cellSize | number
| default: 2 |
82 | | margin | number
| default: cellSize * 4 |
83 | | alt | string
| (optional) |
84 |
85 | #### createSvgTag(opts) => string
86 |
87 | | Param | Type | Description |
88 | | ------------- | -------------------- | --------------------- |
89 | | opts | object
| default: {} |
90 | | opts.cellSize | number
| default: 2 |
91 | | opts.margin | number
| default: cellSize * 4 |
92 | | opts.scalable | boolean
| default: false |
93 |
94 | #### renderTo2dContext(context, cellSize) => void
95 |
96 | --
97 |
98 | This implementation is based on JIS X 0510:1999.
99 |
100 | The word 'QR Code' is registered trademark of DENSO WAVE INCORPORATED
101 |
http://www.denso-wave.com/qrcode/faqpatent-e.html
102 |
--------------------------------------------------------------------------------
/js/demo/assets/qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kazuhikoarase/qrcode-generator/0e51e6310a34b5e4f70280533b3d43e1fc6a0b16/js/demo/assets/qrcode.png
--------------------------------------------------------------------------------
/js/demo/assets/sample.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var body_loadHander = function() {
4 |
5 | var crtOpt = function(value, label) {
6 | var opt = document.createElement('option');
7 | opt.appendChild(document.createTextNode(label) );
8 | opt.value = value;
9 | return opt;
10 | };
11 |
12 | var t = document.forms['qrForm'].elements['t'];
13 | t.appendChild(crtOpt('' + 0, 'Auto Detect') );
14 | for (var i = 1; i <= 40; i += 1) {
15 | t.appendChild(crtOpt('' + i, '' + i) );
16 | }
17 | t.value = '0';
18 |
19 | document.getElementById('dataCaps').appendChild(createDataCapsTable() );
20 |
21 | update_qrcode();
22 | };
23 |
24 | var draw_qrcode = function(text, typeNumber, errorCorrectionLevel) {
25 | document.write(create_qrcode(text, typeNumber, errorCorrectionLevel) );
26 | };
27 |
28 | var create_qrcode = function(text, typeNumber,
29 | errorCorrectionLevel, mode, mb) {
30 |
31 | qrcode.stringToBytes = qrcode.stringToBytesFuncs[mb];
32 |
33 | var qr = qrcode(typeNumber || 4, errorCorrectionLevel || 'M');
34 | qr.addData(text, mode);
35 | qr.make();
36 |
37 | // return qr.createTableTag();
38 | // return qr.createSvgTag();
39 | return qr.createImgTag();
40 | };
41 |
42 | var update_qrcode = function() {
43 | var form = document.forms['qrForm'];
44 | var text = form.elements['msg'].value.
45 | replace(/^[\s\u3000]+|[\s\u3000]+$/g, '');
46 | var t = form.elements['t'].value;
47 | var e = form.elements['e'].value;
48 | var m = form.elements['m'].value;
49 | var mb = form.elements['mb'].value;
50 | document.getElementById('qr').innerHTML =
51 | create_qrcode(text, t, e, m, mb);
52 | };
53 |
54 | var createDataCapsTable = function() {
55 |
56 | var modes = [ 'Numeric', 'Alphanumeric', 'Byte', 'Kanji' ];
57 | var ecls = [ 'L', 'M', 'Q', 'H' ];
58 | var colors = ['255,0,0','255,159,0','0,255,0','0,0,255'];
59 | var getCellBg = function(m, e) {
60 | return 'rgba(' + colors[m] + ',' + (0.1 * (e + 0.5) ) + ')';
61 | };
62 |
63 | var table = document.createElement('table');
64 | var thead = document.createElement('thead');
65 | table.appendChild(thead);
66 | !function() {
67 | var tr = document.createElement('tr');
68 | var th = document.createElement('th');
69 | th.appendChild(document.createTextNode('TypeNumber') );
70 | th.setAttribute('rowspan', '2');
71 | tr.appendChild(th);
72 | for (var m = 0; m < 4; m += 1) {
73 | var th = document.createElement('th');
74 | th.setAttribute('colspan', '4');
75 | th.style.backgroundColor = getCellBg(m, 4);
76 | th.style.textAlign = 'center';
77 | th.appendChild(document.createTextNode(modes[m]) );
78 | tr.appendChild(th);
79 | }
80 | thead.appendChild(tr);
81 | }();
82 | !function() {
83 | var tr = document.createElement('tr');
84 | for (var m = 0; m < 4; m += 1) {
85 | for (var e = 0; e < 4; e += 1) {
86 | var th = document.createElement('th');
87 | th.style.backgroundColor = getCellBg(m, e % 2);
88 | th.style.textAlign = 'center';
89 | th.appendChild(document.createTextNode(ecls[e]) );
90 | tr.appendChild(th);
91 | }
92 | }
93 | thead.appendChild(tr);
94 | }();
95 | var tbody = document.createElement('tbody');
96 | table.appendChild(tbody);
97 | for (var t = 0; t < DATA_CAPS.length; t += 1) {
98 | var tr = document.createElement('tr');
99 | tr.style.backgroundColor = 'rgba(0,0,0,' +
100 | (t % 2 == 0? 0 : 0.1) + ')';
101 | var td = document.createElement('td');
102 | td.style.textAlign = 'center';
103 | td.appendChild(document.createTextNode(''+ (t + 1) ) );
104 | tr.appendChild(td);
105 | for (var m = 0; m < 4; m += 1) {
106 | for (var e = 0; e < 4; e += 1) {
107 | var td = document.createElement('td');
108 | td.style.backgroundColor = getCellBg(m, e % 2);
109 | td.style.textAlign = 'right';
110 | td.appendChild(document.createTextNode(''+ DATA_CAPS[t][e][m]) );
111 | tr.appendChild(td);
112 | }
113 | }
114 | tbody.appendChild(tr);
115 | }
116 | return table;
117 | };
118 |
119 | var DATA_CAPS = [
120 | /* 1 */ [ [41, 25, 17, 10], [34, 20, 14, 8], [27, 16, 11, 7], [17, 10, 7, 4] ],
121 | /* 2 */ [ [77, 47, 32, 20], [63, 38, 26, 16], [48, 29, 20, 12], [34, 20, 14, 8] ],
122 | /* 3 */ [ [127, 77, 53, 32], [101, 61, 42, 26], [77, 47, 32, 20], [58, 35, 24, 15] ],
123 | /* 4 */ [ [187, 114, 78, 48], [149, 90, 62, 38], [111, 67, 46, 28], [82, 50, 34, 21] ],
124 | /* 5 */ [ [255, 154, 106, 65], [202, 122, 84, 52], [144, 87, 60, 37], [106, 64, 44, 27] ],
125 | /* 6 */ [ [322, 195, 134, 82], [255, 154, 106, 65], [178, 108, 74, 45], [139, 84, 58, 36] ],
126 | /* 7 */ [ [370, 224, 154, 95], [293, 178, 122, 75], [207, 125, 86, 53], [154, 93, 64, 39] ],
127 | /* 8 */ [ [461, 279, 192, 118], [365, 221, 152, 93], [259, 157, 108, 66], [202, 122, 84, 52] ],
128 | /* 9 */ [ [552, 335, 230, 141], [432, 262, 180, 111], [312, 189, 130, 80], [235, 143, 98, 60] ],
129 | /* 10 */ [ [652, 395, 271, 167], [513, 311, 213, 131], [364, 221, 151, 93], [288, 174, 119, 74] ],
130 | /* 11 */ [ [772, 468, 321, 198], [604, 366, 251, 155], [427, 259, 177, 109], [331, 200, 137, 85] ],
131 | /* 12 */ [ [883, 535, 367, 226], [691, 419, 287, 177], [489, 296, 203, 125], [374, 227, 155, 96] ],
132 | /* 13 */ [ [1022, 619, 425, 262], [796, 483, 331, 204], [580, 352, 241, 149], [427, 259, 177, 109] ],
133 | /* 14 */ [ [1101, 667, 458, 282], [871, 528, 362, 223], [621, 376, 258, 159], [468, 283, 194, 120] ],
134 | /* 15 */ [ [1250, 758, 520, 320], [991, 600, 412, 254], [703, 426, 292, 180], [530, 321, 220, 136] ],
135 | /* 16 */ [ [1408, 854, 586, 361], [1082, 656, 450, 277], [775, 470, 322, 198], [602, 365, 250, 154] ],
136 | /* 17 */ [ [1548, 938, 644, 397], [1212, 734, 504, 310], [876, 531, 364, 224], [674, 408, 280, 173] ],
137 | /* 18 */ [ [1725, 1046, 718, 442], [1346, 816, 560, 345], [948, 574, 394, 243], [746, 452, 310, 191] ],
138 | /* 19 */ [ [1903, 1153, 792, 488], [1500, 909, 624, 384], [1063, 644, 442, 272], [813, 493, 338, 208] ],
139 | /* 20 */ [ [2061, 1249, 858, 528], [1600, 970, 666, 410], [1159, 702, 482, 297], [919, 557, 382, 235] ],
140 | /* 21 */ [ [2232, 1352, 929, 572], [1708, 1035, 711, 438], [1224, 742, 509, 314], [969, 587, 403, 248] ],
141 | /* 22 */ [ [2409, 1460, 1003, 618], [1872, 1134, 779, 480], [1358, 823, 565, 348], [1056, 640, 439, 270] ],
142 | /* 23 */ [ [2620, 1588, 1091, 672], [2059, 1248, 857, 528], [1468, 890, 611, 376], [1108, 672, 461, 284] ],
143 | /* 24 */ [ [2812, 1704, 1171, 721], [2188, 1326, 911, 561], [1588, 963, 661, 407], [1228, 744, 511, 315] ],
144 | /* 25 */ [ [3057, 1853, 1273, 784], [2395, 1451, 997, 614], [1718, 1041, 715, 440], [1286, 779, 535, 330] ],
145 | /* 26 */ [ [3283, 1990, 1367, 842], [2544, 1542, 1059, 652], [1804, 1094, 751, 462], [1425, 864, 593, 365] ],
146 | /* 27 */ [ [3517, 2132, 1465, 902], [2701, 1637, 1125, 692], [1933, 1172, 805, 496], [1501, 910, 625, 385] ],
147 | /* 28 */ [ [3669, 2223, 1528, 940], [2857, 1732, 1190, 732], [2085, 1263, 868, 534], [1581, 958, 658, 405] ],
148 | /* 29 */ [ [3909, 2369, 1628, 1002], [3035, 1839, 1264, 778], [2181, 1322, 908, 559], [1677, 1016, 698, 430] ],
149 | /* 30 */ [ [4158, 2520, 1732, 1066], [3289, 1994, 1370, 843], [2358, 1429, 982, 604], [1782, 1080, 742, 457] ],
150 | /* 31 */ [ [4417, 2677, 1840, 1132], [3486, 2113, 1452, 894], [2473, 1499, 1030, 634], [1897, 1150, 790, 486] ],
151 | /* 32 */ [ [4686, 2840, 1952, 1201], [3693, 2238, 1538, 947], [2670, 1618, 1112, 684], [2022, 1226, 842, 518] ],
152 | /* 33 */ [ [4965, 3009, 2068, 1273], [3909, 2369, 1628, 1002], [2805, 1700, 1168, 719], [2157, 1307, 898, 553] ],
153 | /* 34 */ [ [5253, 3183, 2188, 1347], [4134, 2506, 1722, 1060], [2949, 1787, 1228, 756], [2301, 1394, 958, 590] ],
154 | /* 35 */ [ [5529, 3351, 2303, 1417], [4343, 2632, 1809, 1113], [3081, 1867, 1283, 790], [2361, 1431, 983, 605] ],
155 | /* 36 */ [ [5836, 3537, 2431, 1496], [4588, 2780, 1911, 1176], [3244, 1966, 1351, 832], [2524, 1530, 1051, 647] ],
156 | /* 37 */ [ [6153, 3729, 2563, 1577], [4775, 2894, 1989, 1224], [3417, 2071, 1423, 876], [2625, 1591, 1093, 673] ],
157 | /* 38 */ [ [6479, 3927, 2699, 1661], [5039, 3054, 2099, 1292], [3599, 2181, 1499, 923], [2735, 1658, 1139, 701] ],
158 | /* 39 */ [ [6743, 4087, 2809, 1729], [5313, 3220, 2213, 1362], [3791, 2298, 1579, 972], [2927, 1774, 1219, 750] ],
159 | /* 40 */ [ [7089, 4296, 2953, 1817], [5596, 3391, 2331, 1435], [3993, 2420, 1663, 1024], [3057, 1852, 1273, 784] ]
160 | ];
161 |
--------------------------------------------------------------------------------
/js/demo/assets/style.css:
--------------------------------------------------------------------------------
1 | BODY, TH, TD, INPUT, SELECT, TEXTAREA {
2 | font-size: 10pt;
3 | font-family: Verdana, Arial, sans-serif;
4 | }
5 |
6 | H1 { font-size: 18pt; }
7 | H2 { font-size: 14pt; }
8 | H3 { font-size: 12pt; }
9 | H4 { font-size: 10pt; }
10 | H5 { font-size: 9pt; }
11 | H6 { font-size: 8pt; }
12 |
13 | BODY {
14 | color: #333333;
15 | background-color: #ffffff;
16 | }
17 |
18 | DIV.page-header {
19 | margin: 16px 0px 16px 0px;
20 | }
21 |
22 | DIV.page-footer {
23 | margin: 16px 0px 16px 0px;
24 | text-align: right;
25 | }
26 |
27 | DIV.section {
28 | margin: 16px 0px 16px 0px;
29 | }
30 |
31 | #dataCaps TABLE {
32 | border-collapse: collapse;
33 | }
34 |
35 | #dataCaps TABLE,
36 | #dataCaps TABLE TH,
37 | #dataCaps TABLE TD {
38 | margin: 0px;
39 | padding: 0px 4px 0px 4px;
40 | border: 1px solid #000000;
41 | }
42 |
--------------------------------------------------------------------------------
/js/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | QR Code Generator
11 |
12 |
13 |
14 |
15 | home
16 |
17 |
18 |
19 |
20 | QR Code Generator
21 |
22 | QR Code Generator implementation in JavaScript, Java and more.
23 |
24 |
25 |
26 |
55 |
Appendix (data capacity in bytes)
56 |
57 |
58 |
59 |
68 |
69 |
70 |
71 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/js/misc/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 | qrcode_SJIS.js
--------------------------------------------------------------------------------
/js/misc/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
14 |
15 |
16 |
17 |
18 |
19 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/js/misc/src/GenSJISSupport.java:
--------------------------------------------------------------------------------
1 | import java.io.BufferedReader;
2 | import java.io.ByteArrayOutputStream;
3 | import java.io.FilterOutputStream;
4 | import java.io.IOException;
5 | import java.io.InputStreamReader;
6 | import java.io.OutputStream;
7 | import java.io.PrintWriter;
8 | import java.util.ArrayList;
9 | import java.util.Collections;
10 | import java.util.Comparator;
11 | import java.util.List;
12 |
13 | /**
14 | * GenSJISSupport
15 | * @author Kazuhiko Arase
16 | */
17 | public class GenSJISSupport {
18 |
19 | private static final String US_ASCII = "ISO-8859-1";
20 |
21 | public static void main(String[] args) throws Exception {
22 | new GenSJISSupport().start();
23 | }
24 |
25 | public void start() throws Exception {
26 |
27 | String templateFile = "qrcode_SJIS.js.tmpl";
28 | String dstFile = "qrcode_SJIS.js";
29 |
30 | List codeTable = new ArrayList();
31 | BufferedReader in = new BufferedReader(new InputStreamReader(
32 | getClass().getResourceAsStream("SJIS.txt"), US_ASCII) );
33 | try {
34 | String line;
35 | while ( (line = in.readLine() ) != null) {
36 | line = line.trim();
37 | if (line.length() == 0 || line.startsWith("#") ) {
38 | continue;
39 | }
40 | String[] code = line.split("\\s+");
41 | if (code.length != 2) {
42 | throw new RuntimeException(line);
43 | }
44 | codeTable.add(new int[]{
45 | Integer.parseInt(code[0], 16),
46 | Integer.parseInt(code[1], 16) });
47 | }
48 | } finally {
49 | in.close();
50 | }
51 |
52 | // JIS X 0201 (191 chars) + JIS X 0208 (6879 chars)
53 | if (codeTable.size() != 7070) {
54 | throw new Exception("!");
55 | }
56 |
57 | // sort by UTF-16
58 | Collections.sort(codeTable, new Comparator() {
59 | @Override
60 | public int compare(int[] c1, int[] c2) {
61 | return c1[1] < c2[1]? -1 : 1;
62 | }
63 | });
64 |
65 | ByteArrayOutputStream bout = new ByteArrayOutputStream();
66 | OutputStream out = new Base64EncodeOutputStream(bout);
67 | try {
68 | for (int[] code : codeTable) {
69 | out.write( (code[1] >>> 8) & 0xff);
70 | out.write(code[1] & 0xff);
71 | out.write( (code[0] >>> 8) & 0xff);
72 | out.write(code[0] & 0xff);
73 | }
74 | } finally {
75 | out.close();
76 | }
77 |
78 | String sjisEncoded = new String(bout.toByteArray(), US_ASCII).
79 | replace("/", "\\/"); // escape slash
80 |
81 | PrintWriter srcOut = new PrintWriter(dstFile, US_ASCII);
82 | try {
83 | BufferedReader tmplIn = new BufferedReader(new InputStreamReader(
84 | getClass().getResourceAsStream(templateFile), US_ASCII) );
85 | try {
86 | String line;
87 | while ( (line = tmplIn.readLine() ) != null) {
88 | srcOut.write(line.replace("@DATA@", sjisEncoded).
89 | replace("@NUM_CHARS@", String.valueOf(codeTable.size() ) ) );
90 | srcOut.write('\n');
91 | }
92 | } finally {
93 | tmplIn.close();
94 | }
95 | } finally {
96 | srcOut.close();
97 | }
98 | }
99 |
100 | protected static class Base64EncodeOutputStream
101 | extends FilterOutputStream {
102 |
103 | private int buffer;
104 | private int buflen;
105 | private int length;
106 |
107 | public Base64EncodeOutputStream(OutputStream out) {
108 | super(out);
109 | this.buffer = 0;
110 | this.buflen = 0;
111 | this.length = 0;
112 | }
113 |
114 | public void write(int n) throws IOException {
115 |
116 | buffer = (buffer << 8) | (n & 0xff);
117 | buflen += 8;
118 | length++;
119 |
120 | while (buflen >= 6) {
121 | writeEncoded(buffer >>> (buflen - 6) );
122 | buflen -= 6;
123 | }
124 | }
125 |
126 | public void flush() throws IOException {
127 |
128 | if (buflen > 0) {
129 | writeEncoded(buffer << (6 - buflen) );
130 | buffer = 0;
131 | buflen = 0;
132 | }
133 |
134 | if (length % 3 != 0) {
135 | // padding
136 | int padlen = 3 - length % 3;
137 | for (int i = 0; i < padlen; i++) {
138 | super.write('=');
139 | }
140 | }
141 |
142 | super.flush();
143 | }
144 |
145 | private void writeEncoded(int b) throws IOException {
146 | super.write(encode(b & 0x3f) );
147 | }
148 |
149 | private static int encode(int n) {
150 | if (n < 0) {
151 | // error.
152 | } else if (n < 26) {
153 | return 'A' + n;
154 | } else if (n < 52) {
155 | return 'a' + (n - 26);
156 | } else if (n < 62) {
157 | return '0' + (n - 52);
158 | } else if (n == 62) {
159 | return '+';
160 | } else if (n == 63) {
161 | return '/';
162 | }
163 | throw new IllegalArgumentException("n:" + n);
164 | }
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/js/misc/src/qrcode_SJIS.js.tmpl:
--------------------------------------------------------------------------------
1 | //---------------------------------------------------------------------
2 | //
3 | // QR Code Generator for JavaScript SJIS Support (optional)
4 | //
5 | // Copyright (c) 2011 Kazuhiko Arase
6 | //
7 | // URL: http://www.d-project.com/
8 | //
9 | // Licensed under the MIT license:
10 | // http://www.opensource.org/licenses/mit-license.php
11 | //
12 | // The word 'QR Code' is registered trademark of
13 | // DENSO WAVE INCORPORATED
14 | // http://www.denso-wave.com/qrcode/faqpatent-e.html
15 | //
16 | //---------------------------------------------------------------------
17 |
18 | !function(qrcode) {
19 |
20 | //---------------------------------------------------------------------
21 | // overwrite qrcode.stringToBytes
22 | //---------------------------------------------------------------------
23 |
24 | qrcode.stringToBytesFuncs['SJIS'] = qrcode.createStringToBytes(
25 | '@DATA@',
26 | @NUM_CHARS@
27 | );
28 | qrcode.stringToBytes = qrcode.stringToBytesFuncs['SJIS'];
29 |
30 | }(qrcode);
31 |
--------------------------------------------------------------------------------
/js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "qrcode-generator",
3 | "version": "1.4.4",
4 | "description": "QR Code Generator implementation in JavaScript.",
5 | "author": "Kazuhiko Arase",
6 | "main": "qrcode.js",
7 | "types": "qrcode.d.ts",
8 | "repository": {
9 | "type": "git",
10 | "url": "https://github.com/kazuhikoarase/qrcode-generator.git"
11 | },
12 | "bugs": {
13 | "url": "https://github.com/kazuhikoarase/qrcode-generator/issues"
14 | },
15 | "keywords": [
16 | "qr",
17 | "qrcode",
18 | "generator"
19 | ],
20 | "license": "MIT",
21 | "directories": {
22 | "test": "test"
23 | },
24 | "scripts": {
25 | "test": "mocha"
26 | },
27 | "devDependencies": {
28 | "mocha": "^5.2.0"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/js/qrcode.d.ts:
--------------------------------------------------------------------------------
1 | //---------------------------------------------------------------------
2 | //
3 | // QR Code Generator for JavaScript - TypeScript Declaration File
4 | //
5 | // Copyright (c) 2016 Kazuhiko Arase
6 | //
7 | // URL: http://www.d-project.com/
8 | //
9 | // Licensed under the MIT license:
10 | // http://www.opensource.org/licenses/mit-license.php
11 | //
12 | // The word 'QR Code' is registered trademark of
13 | // DENSO WAVE INCORPORATED
14 | // http://www.denso-wave.com/qrcode/faqpatent-e.html
15 | //
16 | //---------------------------------------------------------------------
17 |
18 | type TypeNumber =
19 | | 0 // Automatic type number
20 | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
21 | | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20
22 | | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30
23 | | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40
24 | ;
25 |
26 | type ErrorCorrectionLevel = 'L' | 'M' | 'Q' | 'H';
27 |
28 | type Mode = 'Numeric' | 'Alphanumeric' | 'Byte' /* Default */ | 'Kanji';
29 |
30 | interface QRCodeFactory {
31 | (typeNumber: TypeNumber, errorCorrectionLevel: ErrorCorrectionLevel) : QRCode;
32 | stringToBytes(s: string) : number[];
33 | stringToBytesFuncs : { [encoding : string] : (s: string) => number[] };
34 | createStringToBytes(unicodeData: string, numChars: number) :
35 | (s : string) => number[];
36 | }
37 |
38 | interface QRCode {
39 | addData(data: string, mode?: Mode) : void;
40 | make() : void;
41 | getModuleCount() : number;
42 | isDark(row: number, col: number) : boolean;
43 | createImgTag(cellSize?: number, margin?: number) : string;
44 | createSvgTag(cellSize?: number, margin?: number) : string;
45 | createSvgTag(opts? : { cellSize?: number, margin?: number,
46 | scalable?: boolean }) : string;
47 | createDataURL(cellSize?: number, margin?: number) : string;
48 | createTableTag(cellSize?: number, margin?: number) : string;
49 | createASCII(cellSize?: number, margin?: number) : string;
50 | renderTo2dContext(context: CanvasRenderingContext2D, cellSize?: number): void;
51 | }
52 |
53 | declare var qrcode : QRCodeFactory;
54 |
55 | declare module 'qrcode-generator' {
56 | export = qrcode;
57 | }
58 |
--------------------------------------------------------------------------------
/js/qrcode_UTF8.js:
--------------------------------------------------------------------------------
1 | //---------------------------------------------------------------------
2 | //
3 | // QR Code Generator for JavaScript UTF8 Support (optional)
4 | //
5 | // Copyright (c) 2011 Kazuhiko Arase
6 | //
7 | // URL: http://www.d-project.com/
8 | //
9 | // Licensed under the MIT license:
10 | // http://www.opensource.org/licenses/mit-license.php
11 | //
12 | // The word 'QR Code' is registered trademark of
13 | // DENSO WAVE INCORPORATED
14 | // http://www.denso-wave.com/qrcode/faqpatent-e.html
15 | //
16 | //---------------------------------------------------------------------
17 |
18 | !function(qrcode) {
19 |
20 | //---------------------------------------------------------------------
21 | // overwrite qrcode.stringToBytes
22 | //---------------------------------------------------------------------
23 |
24 | qrcode.stringToBytes = qrcode.stringToBytesFuncs['UTF-8'];
25 |
26 | }(qrcode);
27 |
--------------------------------------------------------------------------------
/js/sample.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
11 |
12 |
15 |
16 | QR Code Generator for JavaScript
17 |
18 |
19 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/js/sample.js:
--------------------------------------------------------------------------------
1 |
2 | var body_loadHander = function() {
3 |
4 | var crtOpt = function(value, label) {
5 | var opt = document.createElement('option');
6 | opt.appendChild(document.createTextNode(label) );
7 | opt.value = value;
8 | return opt;
9 | };
10 |
11 | var t = document.forms['qrForm'].elements['t'];
12 | t.appendChild(crtOpt('' + 0, 'Auto Detect') );
13 | for (var i = 1; i <= 40; i += 1) {
14 | t.appendChild(crtOpt('' + i, '' + i) );
15 | }
16 | t.value = '0';
17 |
18 | update_qrcode();
19 | };
20 |
21 | var draw_qrcode = function(text, typeNumber, errorCorrectionLevel) {
22 | document.write(create_qrcode(text, typeNumber, errorCorrectionLevel) );
23 | };
24 |
25 | var create_qrcode = function(text, typeNumber,
26 | errorCorrectionLevel, mode, mb) {
27 |
28 | qrcode.stringToBytes = qrcode.stringToBytesFuncs[mb];
29 |
30 | var qr = qrcode(typeNumber || 4, errorCorrectionLevel || 'M');
31 | qr.addData(text, mode);
32 | qr.make();
33 |
34 | // return qr.createTableTag();
35 | // return qr.createSvgTag();
36 | return qr.createImgTag();
37 | };
38 |
39 | var update_qrcode = function() {
40 | var form = document.forms['qrForm'];
41 | var text = form.elements['msg'].value.
42 | replace(/^[\s\u3000]+|[\s\u3000]+$/g, '');
43 | var t = form.elements['t'].value;
44 | var e = form.elements['e'].value;
45 | var m = form.elements['m'].value;
46 | var mb = form.elements['mb'].value;
47 | document.getElementById('qr').innerHTML =
48 | create_qrcode(text, t, e, m, mb);
49 | };
50 |
--------------------------------------------------------------------------------
/js/test/qrcode.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var qrcode = require('../qrcode.js');
3 |
4 | describe('QRCode', function(){
5 | it('should exist', function(){
6 | assert.ok(qrcode);
7 | });
8 |
9 | it('should be a callable function', function(){
10 | assert.ok(qrcode instanceof Function);
11 | });
12 |
13 | it('should generate correct GIF image tag', function(){
14 | var sourceText = 'http://www.example.com/ążśźęćńół';
15 | var correctImgTag = '
';
16 |
17 | var qr = qrcode(-1, 'M');
18 | qr.addData(unescape(encodeURI(sourceText)));
19 | qr.make();
20 |
21 | assert.strictEqual(qr.createImgTag(), correctImgTag);
22 | });
23 |
24 | it('should generate correct GIF image data', function(){
25 | var sourceText = 'http://www.example.com/ążśźęćńół';
26 | var correctImgData = 'R0lGODdhSgBKAIAAAAAAAP///ywAAAAASgBKAAAC/4yPqcvtD6OctNqLs968+w+G4kiWZgKk6roa7ZEiccACco1TeE6r9997uXYsna0xmw0VLyXsyHBCpKijk9qEPh1UrrXYAy4Xu3FtLEmCr9pucP3NGofyN9peBZ7DE3W9Tqd15+fDlxZXiPVlltiGqDb3BpnHRzj4uNgnSHkjZCiZGbXpRVrlyQZINopE9Jc5CdtaeCj7asvIWEvimet4oqkYKDZiCSrMWtobmcW8esfki2exN4XY2cj7aZQtehxIGHwR+41dDg3tdogLCm7N+ZTOOom+irqZGk//DF/vqDiv7cEpTMW4CZxVYSC5gghpOTt46dg4PGxE5aNUkeItje3Drm3zh9DewIytPl7LuBCkHiImpbEjaAvlloTm+DVzJXNftZM89lAz5vLiOZs94YysqZNmtZ8/vQiFeJApmKUPu30qU6mhKola1V0t6g2ZxqcaAK4biraE2axW004LyeNs1loGHfIkGY3uVLV7Ge4rSayvu7WAHQIGGMvn4KqqdLGd2S5xKE2lit2dfIlswJVhU/5VSRmoyEbr9NbdKhqkq156l8GJCFQZ0aRWFcOWGtZ2aN2IN3LlvPv149Kg8UZqi5ElP+JvkyXH+ns4MFnR/+0F/vEw6YDQk//6Dj68+PHky5s/jz69+vULCgAAOw==';
27 |
28 | var qr = qrcode(-1, 'M');
29 | qr.addData(unescape(encodeURI(sourceText)));
30 | qr.make();
31 |
32 | var data = Buffer.from(qr.createDataURL().replace('data:image/gif;base64,', ''), 'base64');
33 |
34 | assert.strictEqual(data.toString('base64'), correctImgData);
35 | });
36 |
37 | it('should generate correct UTF8 text data', function(){
38 | var sourceText = 'http://www.example.com/ążśźęćńół';
39 | var correctTextData1 = [
40 | '█████████████████████████████████',
41 | '██ ▄▄▄▄▄ █ ▄█▀▄██ ▀▄ ▄██ ▄▄▄▄▄ ██',
42 | '██ █ █ █▀ █▀▄█▀▀█▄▄ ▄█ █ █ ██',
43 | '██ █▄▄▄█ ███ ▀ █▄▀▄▄▀ ▀█ █▄▄▄█ ██',
44 | '██▄▄▄▄▄▄▄█ ▀▄█▄▀▄▀ █▄▀▄█▄▄▄▄▄▄▄██',
45 | '██▄█ ▀▄▄▄█▄▄█▀█▀▀▄█▀▀▀█ ▀▀▄█▄ ██',
46 | '██▀▀▄▀▄█▄█ ▄▄█▄ ▄█ ███ ▀█▀▄▄▀██',
47 | '██ ▄▀█▄▀▄ ▄▀▄ █ ▄▀▀█▀██▀██▄▄▀▀██',
48 | '██ █▀ ▄▄▀▀ ▀█ █▀▄ ▀█▄▀▄▄▄ ▄██',
49 | '██▄██ ▄▄▄▄▄█ ▀▄▄ ▀▀▄▄▄█▄▄█▀ ███',
50 | '██▄█▄██▄▄▄ █ █▄▄▀█▀███▄▀▄▄█▄ ████',
51 | '███▄▄██▄▄▄ ▀▀▄█ █▀ █ ▄ ▄▄▄ ▀▀██',
52 | '██ ▄▄▄▄▄ █ █ ▀█▄█ ▀ ▄ █▄█ ▄█ ▀██',
53 | '██ █ █ █▀▄▄ ▄▀ ▀▄█ █ ▄▄ ▄ ██',
54 | '██ █▄▄▄█ █▄█▄▀█ ▀ ▀ ██ █ █▀▄▀▄██',
55 | '██▄▄▄▄▄▄▄█▄▄█▄█▄███▄▄▄▄████▄█▄███',
56 | '▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀'].join('\n');
57 |
58 | var correctTextData2 = [
59 | ' ▄▄▄▄▄ █ ▄█▀▄██ ▀▄ ▄██ ▄▄▄▄▄ ',
60 | ' █ █ █▀ █▀▄█▀▀█▄▄ ▄█ █ █ ',
61 | ' █▄▄▄█ ███ ▀ █▄▀▄▄▀ ▀█ █▄▄▄█ ',
62 | '▄▄▄▄▄▄▄█ ▀▄█▄▀▄▀ █▄▀▄█▄▄▄▄▄▄▄',
63 | '▄█ ▀▄▄▄█▄▄█▀█▀▀▄█▀▀▀█ ▀▀▄█▄ ',
64 | '▀▀▄▀▄█▄█ ▄▄█▄ ▄█ ███ ▀█▀▄▄▀',
65 | ' ▄▀█▄▀▄ ▄▀▄ █ ▄▀▀█▀██▀██▄▄▀▀',
66 | ' █▀ ▄▄▀▀ ▀█ █▀▄ ▀█▄▀▄▄▄ ▄',
67 | '▄██ ▄▄▄▄▄█ ▀▄▄ ▀▀▄▄▄█▄▄█▀ █',
68 | '▄█▄██▄▄▄ █ █▄▄▀█▀███▄▀▄▄█▄ ██',
69 | '█▄▄██▄▄▄ ▀▀▄█ █▀ █ ▄ ▄▄▄ ▀▀',
70 | ' ▄▄▄▄▄ █ █ ▀█▄█ ▀ ▄ █▄█ ▄█ ▀',
71 | ' █ █ █▀▄▄ ▄▀ ▀▄█ █ ▄▄ ▄ ',
72 | ' █▄▄▄█ █▄█▄▀█ ▀ ▀ ██ █ █▀▄▀▄',
73 | ' ▀ ▀ ▀ ▀▀▀ ▀▀▀▀ ▀ ▀'].join('\n');
74 |
75 | var correctTextData3 = [
76 | '██████████████████████████████████████████████████████████████████',
77 | '██████████████████████████████████████████████████████████████████',
78 | '████ ██ ████ ████ ██ ████ ████',
79 | '████ ██████████ ██ ████ ██████ ██ ██████ ██████████ ████',
80 | '████ ██ ██ ████ ████ ████████ ██ ██ ██ ████',
81 | '████ ██ ██ ██ ██ ████ ██████ ████ ██ ██ ████',
82 | '████ ██ ██ ██████ ██ ██ ██ ██ ████ ██ ██ ████',
83 | '████ ██████████ ██████ ████ ████ ██ ██████████ ████',
84 | '████ ██ ██ ██ ██ ██ ██ ██ ██ ████',
85 | '████████████████████ ██████ ██ ████ ██████████████████████',
86 | '████ ██ ██ ██ ██████████ ██████████ ████ ██ ████',
87 | '████████ ██████████████ ██ ████ ██ ██████ ████',
88 | '████████ ██ ██ ██ ██ ██ ██████ ██████ ██████',
89 | '████ ██ ████████ ████████ ████ ██████ ██ ████ ████',
90 | '████ ████ ██ ██ ██ ██████████████████ ████████',
91 | '████ ██ ████ ██ ██ ██ ██ ██ ██ ████ ████████ ████',
92 | '████ ████ ████ ████ ████ ████ ██ ████',
93 | '████ ██ ████ ██ ██ ██ ████ ██████ ██████',
94 | '████ ████ ██ ██ ████ ██ ████ ██████',
95 | '██████████ ████████████ ████ ██████████████ ██████',
96 | '████ ██ ████ ██ ██ ████████████ ██ ██ ████████',
97 | '████████████████████ ██ ██████ ██ ████████ ████████ ████████',
98 | '██████ ████ ████ ██ ████ ██ ████████',
99 | '████████████████████ ████ ██ ██ ██ ██████ ████',
100 | '████ ██ ██ ████ ██ ██ ██ ██ ██ ██████',
101 | '████ ██████████ ██ ██ ██████ ██ ██████ ████ ████',
102 | '████ ██ ██ ████ ██ ██ ██ ██ ████',
103 | '████ ██ ██ ██ ████ ██ ████ ██ ████ ██ ████',
104 | '████ ██ ██ ██ ██ ████ ██ ██ ████ ██ ████ ██ ████',
105 | '████ ██████████ ████████ ██ ████ ██ ██ ██ ██████',
106 | '████ ██ ██ ██ ██████ ████████ ██ ██████',
107 | '██████████████████████████████████████████████████████████████████',
108 | '██████████████████████████████████████████████████████████████████',].join('\n');
109 |
110 | var qr = qrcode(-1, 'M');
111 | qr.addData(unescape(encodeURI(sourceText)));
112 | qr.make();
113 |
114 | assert.strictEqual(qr.createASCII(), correctTextData1, 'ASCII QRCode of size 1 is incorrect');
115 | assert.strictEqual(qr.createASCII(1, 0), correctTextData2, 'ASCII QRCode of size 1 without margin is incorrect');
116 | assert.strictEqual(qr.createASCII(2), correctTextData3, 'ASCII QRCode of size 2 is incorrect');
117 | });
118 | });
--------------------------------------------------------------------------------
/js/ts-test/.gitignore:
--------------------------------------------------------------------------------
1 | /.tscache
2 | /build
3 | /dist
4 | /node_modules
5 |
--------------------------------------------------------------------------------
/js/ts-test/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 |
3 | grunt.initConfig({
4 | pkg: grunt.file.readJSON('package.json'),
5 | src: 'src',
6 | build: 'build',
7 | dist: 'dist',
8 | ts: {
9 | main: {
10 | options : { sourceMap: false },
11 | src: ['<%= src %>/**/*.ts'],
12 | outDir: '<%= build %>'
13 | }
14 | },
15 | nodeunit: {
16 | all: [ '<%= build %>/*_test.js' ],
17 | options: {
18 | reporter: 'default',
19 | reporterOptions: {
20 | output: 'dist'
21 | }
22 | }
23 | },
24 | clean: {
25 | build : { src: ['<%= build %>', '.tscache'] },
26 | dist : { src: ['<%= dist %>'] }
27 | }
28 | });
29 |
30 | grunt.loadNpmTasks('grunt-contrib-clean');
31 | grunt.loadNpmTasks('grunt-contrib-nodeunit');
32 | grunt.loadNpmTasks("grunt-ts");
33 |
34 | grunt.registerTask('default', ['ts']);
35 |
36 | };
37 |
--------------------------------------------------------------------------------
/js/ts-test/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ts-test",
3 | "version": "0.1.0",
4 | "devDependencies": {
5 | "grunt": "^1.0.0",
6 | "grunt-contrib-clean": "^1.0.0",
7 | "grunt-contrib-nodeunit": "^1.0.0",
8 | "grunt-ts": "^6.0.0-beta.3",
9 | "typescript": "^2.0.0",
10 | "uglify": "^0.1.5",
11 | "qrcode-generator": "file:../"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/js/ts-test/src/.gitignore:
--------------------------------------------------------------------------------
1 | /.baseDir.ts
2 |
--------------------------------------------------------------------------------
/js/ts-test/src/import_test.ts:
--------------------------------------------------------------------------------
1 | declare var require: any;
2 | declare var exports : any;
3 |
4 | import * as imported from 'qrcode-generator';
5 |
6 | exports.requireAndImport = function(test : any) {
7 |
8 | var testQR = function(qrcode : any) {
9 | test.equal(typeof qrcode, 'function');
10 | test.equal(typeof qrcode.stringToBytes, 'function');
11 | };
12 |
13 | var required = require('qrcode-generator');
14 | testQR(required);
15 | testQR(imported);
16 | test.done();
17 | };
18 |
--------------------------------------------------------------------------------
/php/sample.html:
--------------------------------------------------------------------------------
1 | sample_html.php
2 |
3 | sample_image.php
4 |
5 | sample_custom.php
6 |
--------------------------------------------------------------------------------
/php/sample_custom.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kazuhikoarase/qrcode-generator/0e51e6310a34b5e4f70280533b3d43e1fc6a0b16/php/sample_custom.php
--------------------------------------------------------------------------------
/php/sample_html.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kazuhikoarase/qrcode-generator/0e51e6310a34b5e4f70280533b3d43e1fc6a0b16/php/sample_html.php
--------------------------------------------------------------------------------
/php/sample_image.php:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kazuhikoarase/qrcode-generator/0e51e6310a34b5e4f70280533b3d43e1fc6a0b16/php/sample_image.php
--------------------------------------------------------------------------------
/ts/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/image/GIFImage.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ///
4 | 'use strict';
5 | namespace com.d_project.image {
6 |
7 | import OutputStream = com.d_project.io.OutputStream;
8 | import ByteArrayOutputStream = com.d_project.io.ByteArrayOutputStream;
9 | import Base64 = com.d_project.io.Base64;
10 |
11 | /**
12 | * GIF Image (B/W)
13 | * @author Kazuhiko Arase
14 | */
15 | export class GIFImage {
16 |
17 | private width : number;
18 | private height : number;
19 | private data : number[];
20 |
21 | constructor(width : number, height : number) {
22 | this.width = width;
23 | this.height = height;
24 | var size = width * height;
25 | this.data = [];
26 | for (var i = 0; i < size; i += 1) {
27 | this.data.push(0);
28 | }
29 | }
30 |
31 | public setPixel(x : number, y : number, pixel : number) : void {
32 | if (x < 0 || this.width <= x) throw '!' + x;
33 | if (y < 0 || this.height <= y) throw '!' + y;
34 | this.data[y * this.width + x] = pixel;
35 | }
36 |
37 | public getPixel(x : number, y : number) : number {
38 | if (x < 0 || this.width <= x) throw '!' + x;
39 | if (y < 0 || this.height <= y) throw '!' + y;
40 | return this.data[y * this.width + x];
41 | }
42 |
43 | public write(out : OutputStream) : void {
44 |
45 | //---------------------------------
46 | // GIF Signature
47 |
48 | out.writeByte('G'.charCodeAt(0) );
49 | out.writeByte('I'.charCodeAt(0) );
50 | out.writeByte('F'.charCodeAt(0) );
51 | out.writeByte('8'.charCodeAt(0) );
52 | out.writeByte('7'.charCodeAt(0) );
53 | out.writeByte('a'.charCodeAt(0) );
54 |
55 | //---------------------------------
56 | // Screen Descriptor
57 |
58 | this.writeWord(out, this.width);
59 | this.writeWord(out, this.height);
60 |
61 | out.writeByte(0x80); // 2bit
62 | out.writeByte(0);
63 | out.writeByte(0);
64 |
65 | //---------------------------------
66 | // Global Color Map
67 |
68 | // black
69 | out.writeByte(0x00);
70 | out.writeByte(0x00);
71 | out.writeByte(0x00);
72 |
73 | // white
74 | out.writeByte(0xff);
75 | out.writeByte(0xff);
76 | out.writeByte(0xff);
77 |
78 | //---------------------------------
79 | // Image Descriptor
80 |
81 | out.writeByte(','.charCodeAt(0) );
82 | this.writeWord(out, 0);
83 | this.writeWord(out, 0);
84 | this.writeWord(out, this.width);
85 | this.writeWord(out, this.height);
86 | out.writeByte(0);
87 |
88 | //---------------------------------
89 | // Local Color Map
90 |
91 | //---------------------------------
92 | // Raster Data
93 |
94 | var lzwMinCodeSize = 2;
95 | var raster = this.getLZWRaster(lzwMinCodeSize);
96 |
97 | out.writeByte(lzwMinCodeSize);
98 |
99 | var offset : number = 0;
100 |
101 | while (raster.length - offset > 255) {
102 | out.writeByte(255);
103 | this.writeBytes(out, raster, offset, 255);
104 | offset += 255;
105 | }
106 |
107 | out.writeByte(raster.length - offset);
108 | this.writeBytes(out, raster, offset, raster.length - offset);
109 | out.writeByte(0x00);
110 |
111 | //---------------------------------
112 | // GIF Terminator
113 | out.writeByte(';'.charCodeAt(0) );
114 | }
115 |
116 | private getLZWRaster(lzwMinCodeSize : number) : number[] {
117 |
118 | var clearCode = 1 << lzwMinCodeSize;
119 | var endCode = (1 << lzwMinCodeSize) + 1;
120 | var bitLength = lzwMinCodeSize + 1;
121 |
122 | // Setup LZWTable
123 | var table = new LZWTable();
124 |
125 | for (var i = 0; i < clearCode; i += 1) {
126 | table.add(String.fromCharCode(i) );
127 | }
128 | table.add(String.fromCharCode(clearCode) );
129 | table.add(String.fromCharCode(endCode) );
130 |
131 | var byteOut = new ByteArrayOutputStream();
132 | var bitOut = new BitOutputStream(byteOut);
133 |
134 | try {
135 |
136 | // clear code
137 | bitOut.write(clearCode, bitLength);
138 |
139 | var dataIndex = 0;
140 | var s = String.fromCharCode(this.data[dataIndex]);
141 | dataIndex += 1;
142 |
143 | while (dataIndex < this.data.length) {
144 | var c = String.fromCharCode(this.data[dataIndex]);
145 | dataIndex += 1;
146 | if (table.contains(s + c) ) {
147 | s = s + c;
148 | } else {
149 | bitOut.write(table.indexOf(s), bitLength);
150 | if (table.getSize() < 0xfff) {
151 | if (table.getSize() == (1 << bitLength) ) {
152 | bitLength += 1;
153 | }
154 | table.add(s + c);
155 | }
156 | s = c;
157 | }
158 | }
159 |
160 | bitOut.write(table.indexOf(s), bitLength);
161 |
162 | // end code
163 | bitOut.write(endCode, bitLength);
164 |
165 | } finally {
166 | bitOut.close();
167 | }
168 |
169 | return byteOut.toByteArray();
170 | }
171 |
172 | private writeWord(out : OutputStream, i : number) {
173 | out.writeByte(i & 0xff);
174 | out.writeByte( (i >>> 8) & 0xff);
175 | }
176 |
177 | private writeBytes(
178 | out : OutputStream,
179 | bytes : number[], off : number, len : number
180 | ) {
181 | for (var i = 0; i < len; i += 1) {
182 | out.writeByte(bytes[i + off]);
183 | }
184 | }
185 |
186 | public toDataURL() : string {
187 | var bout = new ByteArrayOutputStream();
188 | this.write(bout);
189 | bout.close();
190 | var s = '';
191 | var bytes = Base64.encode(bout.toByteArray() );
192 | for (var i = 0; i < bytes.length; i += 1) {
193 | s += String.fromCharCode(bytes[i]);
194 | }
195 | return 'data:image/gif;base64,' + s;
196 | }
197 | }
198 |
199 | class LZWTable {
200 |
201 | private map : { [key : string] : number; } = {};
202 | private size : number = 0;
203 |
204 | constructor() {
205 | }
206 |
207 | public add(key : string) : void {
208 | if (this.contains(key) ) {
209 | throw 'dup key:' + key;
210 | }
211 | this.map[key] = this.size;
212 | this.size += 1;
213 | }
214 |
215 | public getSize() : number {
216 | return this.size;
217 | }
218 |
219 | public indexOf(key : string) : number {
220 | return this.map[key];
221 | }
222 |
223 | public contains(key : string) : boolean {
224 | return typeof this.map[key] != 'undefined';
225 | }
226 | }
227 |
228 | class BitOutputStream {
229 |
230 | private out : OutputStream;
231 | private bitLength : number;
232 | private bitBuffer : number;
233 |
234 | constructor(out : OutputStream) {
235 | this.out = out;
236 | this.bitLength = 0;
237 | }
238 |
239 | public write(data : number, length : number) : void {
240 |
241 | if ( (data >>> length) != 0) {
242 | throw 'length over';
243 | }
244 |
245 | while (this.bitLength + length >= 8) {
246 | this.out.writeByte(0xff &
247 | ( (data << this.bitLength) | this.bitBuffer) );
248 | length -= (8 - this.bitLength);
249 | data >>>= (8 - this.bitLength);
250 | this.bitBuffer = 0;
251 | this.bitLength = 0;
252 | }
253 |
254 | this.bitBuffer = (data << this.bitLength) | this.bitBuffer;
255 | this.bitLength = this.bitLength + length;
256 | }
257 |
258 | public flush() : void {
259 | if (this.bitLength > 0) {
260 | this.out.writeByte(this.bitBuffer);
261 | }
262 | this.out.flush();
263 | }
264 |
265 | public close() : void {
266 | this.flush();
267 | this.out.close();
268 | }
269 | }
270 | }
271 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/io/Base64.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | namespace com.d_project.io {
3 |
4 | /**
5 | * Base64
6 | * @author Kazuhiko Arase
7 | */
8 | export class Base64 {
9 |
10 | constructor() {
11 | throw 'error';
12 | }
13 |
14 | public static encode(data : number[]) : number[] {
15 | var bout = new ByteArrayOutputStream();
16 | try {
17 | var ostream = new Base64EncodeOutputStream(bout);
18 | try {
19 | ostream.writeBytes(data);
20 | } finally {
21 | ostream.close();
22 | }
23 | } finally {
24 | bout.close();
25 | }
26 | return bout.toByteArray();
27 | }
28 |
29 | public static decode(data : number[]) : number[] {
30 | var bout = new ByteArrayOutputStream();
31 | try {
32 | var istream = new Base64DecodeInputStream(
33 | new ByteArrayInputStream(data) );
34 | try {
35 | var b : number;
36 | while ( (b = istream.readByte() ) != -1) {
37 | bout.writeByte(b);
38 | }
39 | } finally {
40 | istream.close();
41 | }
42 | } finally {
43 | bout.close();
44 | }
45 | return bout.toByteArray();
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/io/Base64DecodeInputStream.ts:
--------------------------------------------------------------------------------
1 | ///
2 | 'use strict';
3 | namespace com.d_project.io {
4 |
5 | /**
6 | * Base64DecodeInputStream
7 | * @author Kazuhiko Arase
8 | */
9 | export class Base64DecodeInputStream extends InputStream {
10 |
11 | private buffer = 0;
12 | private buflen = 0;
13 |
14 | constructor(private istream : InputStream) {
15 | super();
16 | }
17 |
18 | public readByte() : number {
19 |
20 | while (this.buflen < 8) {
21 |
22 | var c = this.istream.readByte();
23 |
24 | if (c == -1) {
25 |
26 | if (this.buflen == 0) {
27 | return -1;
28 | }
29 |
30 | throw 'unexpected end of file./' + this.buflen;
31 |
32 | } else if (c == '='.charCodeAt(0) ) {
33 |
34 | this.buflen = 0;
35 | return -1;
36 |
37 | } else if (Base64DecodeInputStream.isWhitespace(c) ) {
38 | // ignore if whitespace.
39 | continue;
40 | }
41 |
42 | this.buffer = (this.buffer << 6) |
43 | Base64DecodeInputStream.decode(c);
44 | this.buflen += 6;
45 | }
46 |
47 | var n = (this.buffer >>> (this.buflen - 8) ) & 0xff;
48 | this.buflen -= 8;
49 | return n;
50 | }
51 |
52 | private static isWhitespace(c : number) : boolean {
53 | return c == '\v'.charCodeAt(0) ||
54 | c == '\t'.charCodeAt(0) ||
55 | c == '\r'.charCodeAt(0) ||
56 | c == '\n'.charCodeAt(0);
57 | }
58 |
59 | private static decode(c : number) : number {
60 | if ('A'.charCodeAt(0) <= c && c <= 'Z'.charCodeAt(0) ) {
61 | return c - 'A'.charCodeAt(0);
62 | } else if ('a'.charCodeAt(0) <= c && c <= 'z'.charCodeAt(0) ) {
63 | return c - 'a'.charCodeAt(0) + 26;
64 | } else if ('0'.charCodeAt(0) <= c && c <= '9'.charCodeAt(0) ) {
65 | return c - '0'.charCodeAt(0) + 52;
66 | } else if (c == '+'.charCodeAt(0) ) {
67 | return 62;
68 | } else if (c == '/'.charCodeAt(0) ) {
69 | return 63;
70 | } else {
71 | throw 'c:' + c;
72 | }
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/io/Base64EncodeOutputStream.ts:
--------------------------------------------------------------------------------
1 | ///
2 | 'use strict';
3 | namespace com.d_project.io {
4 |
5 | /**
6 | * Base64EncodeOutputStream
7 | * @author Kazuhiko Arase
8 | */
9 | export class Base64EncodeOutputStream extends OutputStream {
10 |
11 | private buffer = 0;
12 | private buflen = 0;
13 | private length = 0;
14 |
15 | constructor(private ostream : OutputStream) {
16 | super();
17 | }
18 |
19 | public writeByte(n : number) : void {
20 |
21 | this.buffer = (this.buffer << 8) | (n & 0xff);
22 | this.buflen += 8;
23 | this.length += 1;
24 |
25 | while (this.buflen >= 6) {
26 | this.writeEncoded(this.buffer >>> (this.buflen - 6) );
27 | this.buflen -= 6;
28 | }
29 | }
30 |
31 | public flush() : void {
32 | if (this.buflen > 0) {
33 | this.writeEncoded(this.buffer << (6 - this.buflen) );
34 | this.buffer = 0;
35 | this.buflen = 0;
36 | }
37 |
38 | if (this.length % 3 != 0) {
39 | // padding
40 | var padlen = 3 - this.length % 3;
41 | for (var i = 0; i < padlen; i += 1) {
42 | this.ostream.writeByte('='.charCodeAt(0) );
43 | }
44 | }
45 | }
46 |
47 | private writeEncoded(b : number) : void {
48 | this.ostream.writeByte(Base64EncodeOutputStream.encode(b & 0x3f) );
49 | }
50 |
51 | private static encode(n : number) : number {
52 | if (n < 0) {
53 | // error.
54 | } else if (n < 26) {
55 | return 'A'.charCodeAt(0) + n;
56 | } else if (n < 52) {
57 | return 'a'.charCodeAt(0) + (n - 26);
58 | } else if (n < 62) {
59 | return '0'.charCodeAt(0) + (n - 52);
60 | } else if (n == 62) {
61 | return '+'.charCodeAt(0);
62 | } else if (n == 63) {
63 | return '/'.charCodeAt(0);
64 | }
65 | throw 'n:' + n;
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/io/ByteArrayInputStream.ts:
--------------------------------------------------------------------------------
1 | ///
2 | 'use strict';
3 | namespace com.d_project.io {
4 |
5 | /**
6 | * ByteArrayInputStream
7 | * @author Kazuhiko Arase
8 | */
9 | export class ByteArrayInputStream extends InputStream {
10 |
11 | private pos = 0;
12 |
13 | constructor(private bytes : number[]) {
14 | super();
15 | }
16 |
17 | public readByte() : number {
18 | if (this.pos < this.bytes.length) {
19 | var b = this.bytes[this.pos];
20 | this.pos += 1;
21 | return b;
22 | }
23 | return -1;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/io/ByteArrayOutputStream.ts:
--------------------------------------------------------------------------------
1 | ///
2 | 'use strict';
3 | namespace com.d_project.io {
4 |
5 | /**
6 | * ByteArrayOutputStream
7 | * @author Kazuhiko Arase
8 | */
9 | export class ByteArrayOutputStream extends OutputStream {
10 |
11 | private bytes : number[] = [];
12 |
13 | constructor() {
14 | super();
15 | }
16 |
17 | public writeByte(b : number) : void {
18 | this.bytes.push(b);
19 | }
20 |
21 | public toByteArray() : number[] {
22 | return this.bytes;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/io/InputStream.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | namespace com.d_project.io {
3 |
4 | /**
5 | * InputStream
6 | * @author Kazuhiko Arase
7 | */
8 | export abstract class InputStream {
9 | constructor() {}
10 | public abstract readByte() : number;
11 | public close() : void {
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/io/OutputStream.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | namespace com.d_project.io {
3 |
4 | /**
5 | * OutputStream
6 | * @author Kazuhiko Arase
7 | */
8 | export abstract class OutputStream {
9 | constructor() {}
10 | public abstract writeByte(b : number) : void;
11 | public writeBytes(bytes : number[]) : void {
12 | for (var i = 0; i < bytes.length; i += 1) {
13 | this.writeByte(bytes[i]);
14 | }
15 | }
16 | public flush() : void {
17 | }
18 | public close() : void {
19 | this.flush();
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/qrcode/BitBuffer.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | namespace com.d_project.qrcode {
3 |
4 | /**
5 | * BitBuffer
6 | * @author Kazuhiko Arase
7 | */
8 | export class BitBuffer {
9 |
10 | private buffer : number[];
11 | private length : number;
12 |
13 | public constructor() {
14 | this.buffer = [];
15 | this.length = 0;
16 | }
17 |
18 | public getBuffer() : number[] {
19 | return this.buffer;
20 | }
21 |
22 | public getLengthInBits() : number {
23 | return this.length;
24 | }
25 |
26 | public toString() : string {
27 | var buffer = '';
28 | for (var i = 0; i < this.getLengthInBits(); i += 1) {
29 | buffer += this.getBit(i)? '1' : '0';
30 | }
31 | return buffer;
32 | }
33 |
34 | private getBit(index : number) : boolean {
35 | return ( (this.buffer[~~(index / 8)] >>> (7 - index % 8) ) & 1) == 1;
36 | }
37 |
38 | public put(num : number, length : number) : void {
39 | for (var i = 0; i < length; i += 1) {
40 | this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1);
41 | }
42 | }
43 |
44 | public putBit(bit : boolean) : void {
45 | if (this.length == this.buffer.length * 8) {
46 | this.buffer.push(0);
47 | }
48 | if (bit) {
49 | this.buffer[~~(this.length / 8)] |= (0x80 >>> (this.length % 8) );
50 | }
51 | this.length += 1;
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/qrcode/ErrorCorrectLevel.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | namespace com.d_project.qrcode {
3 |
4 | /**
5 | * ErrorCorrectLevel
6 | * @author Kazuhiko Arase
7 | */
8 | export enum ErrorCorrectLevel {
9 |
10 | /**
11 | * 7%
12 | */
13 | L = 1,
14 |
15 | /**
16 | * 15%
17 | */
18 | M = 0,
19 |
20 | /**
21 | * 25%
22 | */
23 | Q = 3,
24 |
25 | /**
26 | * 30%
27 | */
28 | H = 2
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/qrcode/MaskPattern.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | namespace com.d_project.qrcode {
3 |
4 | /**
5 | * MaskPattern
6 | * @author Kazuhiko Arase
7 | */
8 | export enum MaskPattern {
9 |
10 | /**
11 | * mask pattern 000
12 | */
13 | PATTERN000 = 0b000,
14 |
15 | /**
16 | * mask pattern 001
17 | */
18 | PATTERN001 = 0b001,
19 |
20 | /**
21 | * mask pattern 010
22 | */
23 | PATTERN010 = 0b010,
24 |
25 | /**
26 | * mask pattern 011
27 | */
28 | PATTERN011 = 0b011,
29 |
30 | /**
31 | * mask pattern 100
32 | */
33 | PATTERN100 = 0b100,
34 |
35 | /**
36 | * mask pattern 101
37 | */
38 | PATTERN101 = 0b101,
39 |
40 | /**
41 | * mask pattern 110
42 | */
43 | PATTERN110 = 0b110,
44 |
45 | /**
46 | * mask pattern 111
47 | */
48 | PATTERN111 = 0b111
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/qrcode/Mode.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | namespace com.d_project.qrcode {
3 |
4 | /**
5 | * Mode
6 | * @author Kazuhiko Arase
7 | */
8 | export enum Mode {
9 |
10 | /**
11 | * number
12 | */
13 | MODE_NUMBER = 1 << 0,
14 |
15 | /**
16 | * alphabet and number
17 | */
18 | MODE_ALPHA_NUM = 1 << 1,
19 |
20 | /**
21 | * 8bit byte
22 | */
23 | MODE_8BIT_BYTE = 1 << 2,
24 |
25 | /**
26 | * KANJI
27 | */
28 | MODE_KANJI = 1 << 3
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/qrcode/Polynomial.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | namespace com.d_project.qrcode {
3 |
4 | /**
5 | * Polynomial
6 | * @author Kazuhiko Arase
7 | */
8 | export class Polynomial {
9 |
10 | private num : number[];
11 |
12 | public constructor(num : number[], shift = 0) {
13 |
14 | var offset = 0;
15 |
16 | while (offset < num.length && num[offset] == 0) {
17 | offset += 1;
18 | }
19 |
20 | this.num = [];
21 | var len = num.length - offset;
22 | for (var i = 0; i < len; i += 1) {
23 | this.num.push(num[offset + i]);
24 | }
25 | for (var i = 0; i < shift; i += 1) {
26 | this.num.push(0);
27 | }
28 | }
29 |
30 | public getAt(index : number) : number{
31 | return this.num[index];
32 | }
33 |
34 | public getLength() : number {
35 | return this.num.length;
36 | }
37 |
38 | public toString() : string {
39 | var buffer = '';
40 | for (var i = 0; i < this.getLength(); i += 1) {
41 | if (i > 0) {
42 | buffer += ',';
43 | }
44 | buffer += this.getAt(i);
45 | }
46 | return buffer.toString();
47 | }
48 |
49 | public toLogString() : string {
50 | var buffer = '';
51 | for (var i = 0; i < this.getLength(); i += 1) {
52 | if (i > 0) {
53 | buffer += ',';
54 | }
55 | buffer += QRMath.glog(this.getAt(i) );
56 | }
57 | return buffer.toString();
58 | }
59 |
60 | public multiply(e : Polynomial) : Polynomial {
61 | var num : number[] = [];
62 | var len = this.getLength() + e.getLength() - 1;
63 | for (var i = 0; i < len; i += 1) {
64 | num.push(0);
65 | }
66 | for (var i = 0; i < this.getLength(); i += 1) {
67 | for (var j = 0; j < e.getLength(); j += 1) {
68 | num[i + j] ^= QRMath.gexp(QRMath.glog(this.getAt(i) ) +
69 | QRMath.glog(e.getAt(j) ) );
70 | }
71 | }
72 | return new Polynomial(num);
73 | }
74 |
75 | public mod(e : Polynomial) : Polynomial {
76 |
77 | if (this.getLength() - e.getLength() < 0) {
78 | return this;
79 | }
80 |
81 | var ratio = QRMath.glog(this.getAt(0) ) - QRMath.glog(e.getAt(0) );
82 |
83 | // create copy
84 | var num : number[] = [];
85 | for (var i = 0; i < this.getLength(); i += 1) {
86 | num.push(this.getAt(i) );
87 | }
88 |
89 | // subtract and calc rest.
90 | for (var i = 0; i < e.getLength(); i += 1) {
91 | num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i) ) + ratio);
92 | }
93 |
94 | // call recursively
95 | return new Polynomial(num).mod(e);
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/qrcode/QR8BitByte.ts:
--------------------------------------------------------------------------------
1 | ///
2 | 'use strict';
3 | namespace com.d_project.qrcode {
4 |
5 | /**
6 | * QR8BitByte
7 | * @author Kazuhiko Arase
8 | */
9 | export class QR8BitByte extends QRData {
10 |
11 | constructor(data : string) {
12 | super(Mode.MODE_8BIT_BYTE, data);
13 | }
14 |
15 | public write(buffer : BitBuffer) : void {
16 | var data = QRCode.stringToBytes(this.getData() );
17 | for (var i = 0; i < data.length; i += 1) {
18 | buffer.put(data[i], 8);
19 | }
20 | }
21 |
22 | public getLength() : number {
23 | return QRCode.stringToBytes(this.getData() ).length;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/qrcode/QRAlphaNum.ts:
--------------------------------------------------------------------------------
1 | ///
2 | 'use strict';
3 | namespace com.d_project.qrcode {
4 |
5 | /**
6 | * QRAlphaNum
7 | * @author Kazuhiko Arase
8 | */
9 | export class QRAlphaNum extends QRData {
10 |
11 | constructor(data : string) {
12 | super(Mode.MODE_ALPHA_NUM, data);
13 | }
14 |
15 | public write(buffer : BitBuffer) : void {
16 |
17 | var s = this.getData();
18 |
19 | var i = 0;
20 |
21 | while (i + 1 < s.length) {
22 | buffer.put(
23 | QRAlphaNum.getCode(s.charAt(i) ) * 45 +
24 | QRAlphaNum.getCode(s.charAt(i + 1) ), 11);
25 | i += 2;
26 | }
27 |
28 | if (i < s.length) {
29 | buffer.put(QRAlphaNum.getCode(s.charAt(i) ), 6);
30 | }
31 | }
32 |
33 | public getLength() : number {
34 | return this.getData().length;
35 | }
36 |
37 | private static getCode(c : string) : number {
38 |
39 | if ('0' <= c && c <= '9') {
40 | return c.charCodeAt(0) - '0'.charCodeAt(0);
41 | } else if ('A' <= c && c <= 'Z') {
42 | return c.charCodeAt(0) - 'A'.charCodeAt(0) + 10;
43 | } else {
44 | switch (c) {
45 | case ' ' : return 36;
46 | case '$' : return 37;
47 | case '%' : return 38;
48 | case '*' : return 39;
49 | case '+' : return 40;
50 | case '-' : return 41;
51 | case '.' : return 42;
52 | case '/' : return 43;
53 | case ':' : return 44;
54 | default :
55 | throw 'illegal char :' + c;
56 | }
57 | }
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/qrcode/QRData.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | namespace com.d_project.qrcode {
3 |
4 | /**
5 | * QRData
6 | * @author Kazuhiko Arase
7 | */
8 | export abstract class QRData {
9 |
10 | constructor(private mode : Mode, private data : string) {
11 | }
12 |
13 | public getMode() : Mode {
14 | return this.mode;
15 | }
16 |
17 | public getData() : string {
18 | return this.data;
19 | }
20 |
21 | public abstract getLength() : number;
22 |
23 | public abstract write(buffer : BitBuffer) : void;
24 |
25 | public getLengthInBits(typeNumber : number) : number {
26 |
27 | if (1 <= typeNumber && typeNumber < 10) {
28 |
29 | // 1 - 9
30 |
31 | switch(this.mode) {
32 | case Mode.MODE_NUMBER : return 10;
33 | case Mode.MODE_ALPHA_NUM : return 9;
34 | case Mode.MODE_8BIT_BYTE : return 8;
35 | case Mode.MODE_KANJI : return 8;
36 | default :
37 | throw 'mode:' + this.mode;
38 | }
39 |
40 | } else if (typeNumber < 27) {
41 |
42 | // 10 - 26
43 |
44 | switch(this.mode) {
45 | case Mode.MODE_NUMBER : return 12;
46 | case Mode.MODE_ALPHA_NUM : return 11;
47 | case Mode.MODE_8BIT_BYTE : return 16;
48 | case Mode.MODE_KANJI : return 10;
49 | default :
50 | throw 'mode:' + this.mode;
51 | }
52 |
53 | } else if (typeNumber < 41) {
54 |
55 | // 27 - 40
56 |
57 | switch(this.mode) {
58 | case Mode.MODE_NUMBER : return 14;
59 | case Mode.MODE_ALPHA_NUM : return 13;
60 | case Mode.MODE_8BIT_BYTE : return 16;
61 | case Mode.MODE_KANJI : return 12;
62 | default :
63 | throw 'mode:' + this.mode;
64 | }
65 |
66 | } else {
67 | throw 'typeNumber:' + typeNumber;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/qrcode/QRKanji.ts:
--------------------------------------------------------------------------------
1 | ///
2 | 'use strict';
3 | namespace com.d_project.qrcode {
4 |
5 | /**
6 | * QRKanji(SJIS only)
7 | * @author Kazuhiko Arase
8 | */
9 | export class QRKanji extends QRData {
10 |
11 | constructor(data : string) {
12 | super(Mode.MODE_KANJI, data);
13 | }
14 |
15 | public write(buffer : BitBuffer) : void {
16 |
17 | var data = QRCode.stringToBytes(this.getData() );
18 |
19 | var i = 0;
20 |
21 | while (i + 1 < data.length) {
22 |
23 | var c = ( (0xff & data[i]) << 8) | (0xff & data[i + 1]);
24 |
25 | if (0x8140 <= c && c <= 0x9FFC) {
26 | c -= 0x8140;
27 | } else if (0xE040 <= c && c <= 0xEBBF) {
28 | c -= 0xC140;
29 | } else {
30 | throw 'illegal char at ' + (i + 1) + '/' + c;
31 | }
32 |
33 | c = ( (c >>> 8) & 0xff) * 0xC0 + (c & 0xff);
34 |
35 | buffer.put(c, 13);
36 |
37 | i += 2;
38 | }
39 |
40 | if (i < data.length) {
41 | throw 'illegal char at ' + (i + 1);
42 | }
43 | }
44 |
45 | public getLength() : number {
46 | return QRCode.stringToBytes(this.getData() ).length / 2;
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/qrcode/QRMath.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | namespace com.d_project.qrcode {
3 |
4 | /**
5 | * QRMath
6 | * @author Kazuhiko Arase
7 | */
8 | export class QRMath {
9 |
10 | constructor() {
11 | throw 'error';
12 | }
13 |
14 | private static EXP_TABLE : number[];
15 | private static LOG_TABLE : number[];
16 |
17 | private static initialize = function() {
18 | QRMath.EXP_TABLE = [];
19 | QRMath.LOG_TABLE = [];
20 | for (var i = 0; i < 256; i += 1) {
21 | QRMath.EXP_TABLE.push(i < 8? 1 << i :
22 | QRMath.EXP_TABLE[i - 4] ^
23 | QRMath.EXP_TABLE[i - 5] ^
24 | QRMath.EXP_TABLE[i - 6] ^
25 | QRMath.EXP_TABLE[i - 8]);
26 | QRMath.LOG_TABLE.push(0);
27 | }
28 | for (var i = 0; i < 255; i += 1) {
29 | QRMath.LOG_TABLE[QRMath.EXP_TABLE[i] ] = i;
30 | }
31 | }();
32 |
33 | public static glog(n : number) : number {
34 | if (n < 1) {
35 | throw 'log(' + n + ')';
36 | }
37 | return QRMath.LOG_TABLE[n];
38 | }
39 |
40 | public static gexp(n : number) : number {
41 | while (n < 0) {
42 | n += 255;
43 | }
44 | while (n >= 256) {
45 | n -= 255;
46 | }
47 | return QRMath.EXP_TABLE[n];
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/qrcode/QRNumber.ts:
--------------------------------------------------------------------------------
1 | ///
2 | 'use strict';
3 | namespace com.d_project.qrcode {
4 |
5 | /**
6 | * QRNumber
7 | * @author Kazuhiko Arase
8 | */
9 | export class QRNumber extends QRData {
10 |
11 | constructor(data : string) {
12 | super(Mode.MODE_NUMBER, data);
13 | }
14 |
15 | public write(buffer : BitBuffer) : void {
16 |
17 | var data = this.getData();
18 |
19 | var i = 0;
20 |
21 | while (i + 2 < data.length) {
22 | buffer.put(QRNumber.strToNum(data.substring(i, i + 3) ), 10);
23 | i += 3;
24 | }
25 |
26 | if (i < data.length) {
27 | if (data.length - i == 1) {
28 | buffer.put(QRNumber.strToNum(data.substring(i, i + 1) ), 4);
29 | } else if (data.length - i == 2) {
30 | buffer.put(QRNumber.strToNum(data.substring(i, i + 2) ), 7);
31 | }
32 | }
33 | }
34 |
35 | public getLength() : number {
36 | return this.getData().length;
37 | }
38 |
39 | private static strToNum(s : string) : number {
40 | var num = 0;
41 | for (var i = 0; i < s.length; i += 1) {
42 | num = num * 10 + QRNumber.chatToNum(s.charAt(i) );
43 | }
44 | return num;
45 | }
46 |
47 | private static chatToNum(c : string) : number {
48 | if ('0' <= c && c <= '9') {
49 | return c.charCodeAt(0) - '0'.charCodeAt(0);
50 | }
51 | throw 'illegal char :' + c;
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/qrcode/QRUtil.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | namespace com.d_project.qrcode {
3 |
4 | /**
5 | * QRUtil
6 | * @author Kazuhiko Arase
7 | */
8 | export class QRUtil {
9 |
10 | constructor() {
11 | throw 'error';
12 | }
13 |
14 | public static getPatternPosition(typeNumber: number) : number[] {
15 | return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
16 | }
17 |
18 | private static PATTERN_POSITION_TABLE = [
19 | [],
20 | [6, 18],
21 | [6, 22],
22 | [6, 26],
23 | [6, 30],
24 | [6, 34],
25 | [6, 22, 38],
26 | [6, 24, 42],
27 | [6, 26, 46],
28 | [6, 28, 50],
29 | [6, 30, 54],
30 | [6, 32, 58],
31 | [6, 34, 62],
32 | [6, 26, 46, 66],
33 | [6, 26, 48, 70],
34 | [6, 26, 50, 74],
35 | [6, 30, 54, 78],
36 | [6, 30, 56, 82],
37 | [6, 30, 58, 86],
38 | [6, 34, 62, 90],
39 | [6, 28, 50, 72, 94],
40 | [6, 26, 50, 74, 98],
41 | [6, 30, 54, 78, 102],
42 | [6, 28, 54, 80, 106],
43 | [6, 32, 58, 84, 110],
44 | [6, 30, 58, 86, 114],
45 | [6, 34, 62, 90, 118],
46 | [6, 26, 50, 74, 98, 122],
47 | [6, 30, 54, 78, 102, 126],
48 | [6, 26, 52, 78, 104, 130],
49 | [6, 30, 56, 82, 108, 134],
50 | [6, 34, 60, 86, 112, 138],
51 | [6, 30, 58, 86, 114, 142],
52 | [6, 34, 62, 90, 118, 146],
53 | [6, 30, 54, 78, 102, 126, 150],
54 | [6, 24, 50, 76, 102, 128, 154],
55 | [6, 28, 54, 80, 106, 132, 158],
56 | [6, 32, 58, 84, 110, 136, 162],
57 | [6, 26, 54, 82, 110, 138, 166],
58 | [6, 30, 58, 86, 114, 142, 170]
59 | ];
60 |
61 | private static MAX_LENGTH = [
62 | [ [41, 25, 17, 10], [34, 20, 14, 8], [27, 16, 11, 7], [17, 10, 7, 4] ],
63 | [ [77, 47, 32, 20], [63, 38, 26, 16], [48, 29, 20, 12], [34, 20, 14, 8] ],
64 | [ [127, 77, 53, 32], [101, 61, 42, 26], [77, 47, 32, 20], [58, 35, 24, 15] ],
65 | [ [187, 114, 78, 48], [149, 90, 62, 38], [111, 67, 46, 28], [82, 50, 34, 21] ],
66 | [ [255, 154, 106, 65], [202, 122, 84, 52], [144, 87, 60, 37], [106, 64, 44, 27] ],
67 | [ [322, 195, 134, 82], [255, 154, 106, 65], [178, 108, 74, 45], [139, 84, 58, 36] ],
68 | [ [370, 224, 154, 95], [293, 178, 122, 75], [207, 125, 86, 53], [154, 93, 64, 39] ],
69 | [ [461, 279, 192, 118], [365, 221, 152, 93], [259, 157, 108, 66], [202, 122, 84, 52] ],
70 | [ [552, 335, 230, 141], [432, 262, 180, 111], [312, 189, 130, 80], [235, 143, 98, 60] ],
71 | [ [652, 395, 271, 167], [513, 311, 213, 131], [364, 221, 151, 93], [288, 174, 119, 74] ]
72 | ];
73 |
74 | public static getMaxLength(
75 | typeNumber : number,
76 | mode : Mode,
77 | errorCorrectLevel : ErrorCorrectLevel
78 | ) : number {
79 |
80 | var t = typeNumber - 1;
81 | var e = 0;
82 | var m = 0;
83 |
84 | switch(errorCorrectLevel) {
85 | case ErrorCorrectLevel.L : e = 0; break;
86 | case ErrorCorrectLevel.M : e = 1; break;
87 | case ErrorCorrectLevel.Q : e = 2; break;
88 | case ErrorCorrectLevel.H : e = 3; break;
89 | default :
90 | throw 'e:' + errorCorrectLevel;
91 | }
92 |
93 | switch(mode) {
94 | case Mode.MODE_NUMBER : m = 0; break;
95 | case Mode.MODE_ALPHA_NUM : m = 1; break;
96 | case Mode.MODE_8BIT_BYTE : m = 2; break;
97 | case Mode.MODE_KANJI : m = 3; break;
98 | default :
99 | throw 'm:' + mode;
100 | }
101 |
102 | return QRUtil.MAX_LENGTH[t][e][m];
103 | }
104 |
105 | public static getErrorCorrectPolynomial(
106 | errorCorrectLength : number) : Polynomial {
107 |
108 | var a = new Polynomial([1]);
109 |
110 | for (var i = 0; i < errorCorrectLength; i += 1) {
111 | a = a.multiply(new Polynomial([1, QRMath.gexp(i)]) );
112 | }
113 |
114 | return a;
115 | }
116 |
117 | public static getMaskFunc(
118 | maskPattern : number
119 | ) : (i : number, j : number) => boolean {
120 |
121 | switch (maskPattern) {
122 |
123 | case MaskPattern.PATTERN000 :
124 | return (i : number, j : number) => (i + j) % 2 == 0;
125 | case MaskPattern.PATTERN001 :
126 | return (i : number, j : number) => i % 2 == 0;
127 | case MaskPattern.PATTERN010 :
128 | return (i : number, j : number) => j % 3 == 0;
129 | case MaskPattern.PATTERN011 :
130 | return (i : number, j : number) => (i + j) % 3 == 0;
131 | case MaskPattern.PATTERN100 :
132 | return (i : number, j : number) => (~~(i / 2) + ~~(j / 3) ) % 2 == 0;
133 | case MaskPattern.PATTERN101 :
134 | return (i : number, j : number) => (i * j) % 2 + (i * j) % 3 == 0;
135 | case MaskPattern.PATTERN110 :
136 | return (i : number, j : number) => ( (i * j) % 2 + (i * j) % 3) % 2 == 0;
137 | case MaskPattern.PATTERN111 :
138 | return (i : number, j : number) => ( (i * j) % 3 + (i + j) % 2) % 2 == 0;
139 |
140 | default :
141 | throw 'mask:' + maskPattern;
142 | }
143 | }
144 |
145 | public static getLostPoint(qrCode : QRCode) : number {
146 |
147 | var moduleCount = qrCode.getModuleCount();
148 |
149 | var lostPoint = 0;
150 |
151 | // LEVEL1
152 |
153 | for (var row = 0; row < moduleCount; row += 1) {
154 |
155 | for (var col = 0; col < moduleCount; col += 1) {
156 |
157 | var sameCount = 0;
158 | var dark = qrCode.isDark(row, col);
159 |
160 | for (var r = -1; r <= 1; r += 1) {
161 |
162 | if (row + r < 0 || moduleCount <= row + r) {
163 | continue;
164 | }
165 |
166 | for (var c = -1; c <= 1; c += 1) {
167 |
168 | if (col + c < 0 || moduleCount <= col + c) {
169 | continue;
170 | }
171 |
172 | if (r == 0 && c == 0) {
173 | continue;
174 | }
175 |
176 | if (dark == qrCode.isDark(row + r, col + c) ) {
177 | sameCount += 1;
178 | }
179 | }
180 | }
181 |
182 | if (sameCount > 5) {
183 | lostPoint += (3 + sameCount - 5);
184 | }
185 | }
186 | }
187 |
188 | // LEVEL2
189 |
190 | for (var row = 0; row < moduleCount - 1; row += 1) {
191 | for (var col = 0; col < moduleCount - 1; col += 1) {
192 | var count = 0;
193 | if (qrCode.isDark(row, col ) ) count += 1;
194 | if (qrCode.isDark(row + 1, col ) ) count += 1;
195 | if (qrCode.isDark(row, col + 1) ) count += 1;
196 | if (qrCode.isDark(row + 1, col + 1) ) count += 1;
197 | if (count == 0 || count == 4) {
198 | lostPoint += 3;
199 | }
200 | }
201 | }
202 |
203 | // LEVEL3
204 |
205 | for (var row = 0; row < moduleCount; row += 1) {
206 | for (var col = 0; col < moduleCount - 6; col += 1) {
207 | if (qrCode.isDark(row, col)
208 | && !qrCode.isDark(row, col + 1)
209 | && qrCode.isDark(row, col + 2)
210 | && qrCode.isDark(row, col + 3)
211 | && qrCode.isDark(row, col + 4)
212 | && !qrCode.isDark(row, col + 5)
213 | && qrCode.isDark(row, col + 6) ) {
214 | lostPoint += 40;
215 | }
216 | }
217 | }
218 |
219 | for (var col = 0; col < moduleCount; col += 1) {
220 | for (var row = 0; row < moduleCount - 6; row += 1) {
221 | if (qrCode.isDark(row, col)
222 | && !qrCode.isDark(row + 1, col)
223 | && qrCode.isDark(row + 2, col)
224 | && qrCode.isDark(row + 3, col)
225 | && qrCode.isDark(row + 4, col)
226 | && !qrCode.isDark(row + 5, col)
227 | && qrCode.isDark(row + 6, col) ) {
228 | lostPoint += 40;
229 | }
230 | }
231 | }
232 |
233 | // LEVEL4
234 |
235 | var darkCount = 0;
236 |
237 | for (var col = 0; col < moduleCount; col += 1) {
238 | for (var row = 0; row < moduleCount; row += 1) {
239 | if (qrCode.isDark(row, col) ) {
240 | darkCount += 1;
241 | }
242 | }
243 | }
244 |
245 | var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
246 | lostPoint += ratio * 10;
247 |
248 | return lostPoint;
249 | }
250 |
251 | public static getBCHTypeInfo(data : number) : number {
252 | var d = data << 10;
253 | while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
254 | d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) -
255 | QRUtil.getBCHDigit(QRUtil.G15) ) );
256 | }
257 | return ( (data << 10) | d) ^ QRUtil.G15_MASK;
258 | }
259 |
260 | public static getBCHTypeNumber(data : number) : number {
261 | var d = data << 12;
262 | while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
263 | d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) -
264 | QRUtil.getBCHDigit(QRUtil.G18) ) );
265 | }
266 | return (data << 12) | d;
267 | }
268 |
269 | private static G15 = (1 << 10) | (1 << 8) | (1 << 5)
270 | | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
271 |
272 | private static G18 = (1 << 12) | (1 << 11) | (1 << 10)
273 | | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);
274 |
275 | private static G15_MASK = (1 << 14) | (1 << 12) | (1 << 10)
276 | | (1 << 4) | (1 << 1);
277 |
278 | private static getBCHDigit(data : number) : number {
279 | var digit = 0;
280 | while (data != 0) {
281 | digit += 1;
282 | data >>>= 1;
283 | }
284 | return digit;
285 | }
286 | }
287 | }
288 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/qrcode/RSBlock.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | namespace com.d_project.qrcode {
3 |
4 | /**
5 | * RSBlock
6 | * @author Kazuhiko Arase
7 | */
8 | export class RSBlock {
9 |
10 | private static RS_BLOCK_TABLE = [
11 |
12 | // L
13 | // M
14 | // Q
15 | // H
16 |
17 | // 1
18 | [1, 26, 19],
19 | [1, 26, 16],
20 | [1, 26, 13],
21 | [1, 26, 9],
22 |
23 | // 2
24 | [1, 44, 34],
25 | [1, 44, 28],
26 | [1, 44, 22],
27 | [1, 44, 16],
28 |
29 | // 3
30 | [1, 70, 55],
31 | [1, 70, 44],
32 | [2, 35, 17],
33 | [2, 35, 13],
34 |
35 | // 4
36 | [1, 100, 80],
37 | [2, 50, 32],
38 | [2, 50, 24],
39 | [4, 25, 9],
40 |
41 | // 5
42 | [1, 134, 108],
43 | [2, 67, 43],
44 | [2, 33, 15, 2, 34, 16],
45 | [2, 33, 11, 2, 34, 12],
46 |
47 | // 6
48 | [2, 86, 68],
49 | [4, 43, 27],
50 | [4, 43, 19],
51 | [4, 43, 15],
52 |
53 | // 7
54 | [2, 98, 78],
55 | [4, 49, 31],
56 | [2, 32, 14, 4, 33, 15],
57 | [4, 39, 13, 1, 40, 14],
58 |
59 | // 8
60 | [2, 121, 97],
61 | [2, 60, 38, 2, 61, 39],
62 | [4, 40, 18, 2, 41, 19],
63 | [4, 40, 14, 2, 41, 15],
64 |
65 | // 9
66 | [2, 146, 116],
67 | [3, 58, 36, 2, 59, 37],
68 | [4, 36, 16, 4, 37, 17],
69 | [4, 36, 12, 4, 37, 13],
70 |
71 | // 10
72 | [2, 86, 68, 2, 87, 69],
73 | [4, 69, 43, 1, 70, 44],
74 | [6, 43, 19, 2, 44, 20],
75 | [6, 43, 15, 2, 44, 16],
76 |
77 | // 11
78 | [4, 101, 81],
79 | [1, 80, 50, 4, 81, 51],
80 | [4, 50, 22, 4, 51, 23],
81 | [3, 36, 12, 8, 37, 13],
82 |
83 | // 12
84 | [2, 116, 92, 2, 117, 93],
85 | [6, 58, 36, 2, 59, 37],
86 | [4, 46, 20, 6, 47, 21],
87 | [7, 42, 14, 4, 43, 15],
88 |
89 | // 13
90 | [4, 133, 107],
91 | [8, 59, 37, 1, 60, 38],
92 | [8, 44, 20, 4, 45, 21],
93 | [12, 33, 11, 4, 34, 12],
94 |
95 | // 14
96 | [3, 145, 115, 1, 146, 116],
97 | [4, 64, 40, 5, 65, 41],
98 | [11, 36, 16, 5, 37, 17],
99 | [11, 36, 12, 5, 37, 13],
100 |
101 | // 15
102 | [5, 109, 87, 1, 110, 88],
103 | [5, 65, 41, 5, 66, 42],
104 | [5, 54, 24, 7, 55, 25],
105 | [11, 36, 12, 7, 37, 13],
106 |
107 | // 16
108 | [5, 122, 98, 1, 123, 99],
109 | [7, 73, 45, 3, 74, 46],
110 | [15, 43, 19, 2, 44, 20],
111 | [3, 45, 15, 13, 46, 16],
112 |
113 | // 17
114 | [1, 135, 107, 5, 136, 108],
115 | [10, 74, 46, 1, 75, 47],
116 | [1, 50, 22, 15, 51, 23],
117 | [2, 42, 14, 17, 43, 15],
118 |
119 | // 18
120 | [5, 150, 120, 1, 151, 121],
121 | [9, 69, 43, 4, 70, 44],
122 | [17, 50, 22, 1, 51, 23],
123 | [2, 42, 14, 19, 43, 15],
124 |
125 | // 19
126 | [3, 141, 113, 4, 142, 114],
127 | [3, 70, 44, 11, 71, 45],
128 | [17, 47, 21, 4, 48, 22],
129 | [9, 39, 13, 16, 40, 14],
130 |
131 | // 20
132 | [3, 135, 107, 5, 136, 108],
133 | [3, 67, 41, 13, 68, 42],
134 | [15, 54, 24, 5, 55, 25],
135 | [15, 43, 15, 10, 44, 16],
136 |
137 | // 21
138 | [4, 144, 116, 4, 145, 117],
139 | [17, 68, 42],
140 | [17, 50, 22, 6, 51, 23],
141 | [19, 46, 16, 6, 47, 17],
142 |
143 | // 22
144 | [2, 139, 111, 7, 140, 112],
145 | [17, 74, 46],
146 | [7, 54, 24, 16, 55, 25],
147 | [34, 37, 13],
148 |
149 | // 23
150 | [4, 151, 121, 5, 152, 122],
151 | [4, 75, 47, 14, 76, 48],
152 | [11, 54, 24, 14, 55, 25],
153 | [16, 45, 15, 14, 46, 16],
154 |
155 | // 24
156 | [6, 147, 117, 4, 148, 118],
157 | [6, 73, 45, 14, 74, 46],
158 | [11, 54, 24, 16, 55, 25],
159 | [30, 46, 16, 2, 47, 17],
160 |
161 | // 25
162 | [8, 132, 106, 4, 133, 107],
163 | [8, 75, 47, 13, 76, 48],
164 | [7, 54, 24, 22, 55, 25],
165 | [22, 45, 15, 13, 46, 16],
166 |
167 | // 26
168 | [10, 142, 114, 2, 143, 115],
169 | [19, 74, 46, 4, 75, 47],
170 | [28, 50, 22, 6, 51, 23],
171 | [33, 46, 16, 4, 47, 17],
172 |
173 | // 27
174 | [8, 152, 122, 4, 153, 123],
175 | [22, 73, 45, 3, 74, 46],
176 | [8, 53, 23, 26, 54, 24],
177 | [12, 45, 15, 28, 46, 16],
178 |
179 | // 28
180 | [3, 147, 117, 10, 148, 118],
181 | [3, 73, 45, 23, 74, 46],
182 | [4, 54, 24, 31, 55, 25],
183 | [11, 45, 15, 31, 46, 16],
184 |
185 | // 29
186 | [7, 146, 116, 7, 147, 117],
187 | [21, 73, 45, 7, 74, 46],
188 | [1, 53, 23, 37, 54, 24],
189 | [19, 45, 15, 26, 46, 16],
190 |
191 | // 30
192 | [5, 145, 115, 10, 146, 116],
193 | [19, 75, 47, 10, 76, 48],
194 | [15, 54, 24, 25, 55, 25],
195 | [23, 45, 15, 25, 46, 16],
196 |
197 | // 31
198 | [13, 145, 115, 3, 146, 116],
199 | [2, 74, 46, 29, 75, 47],
200 | [42, 54, 24, 1, 55, 25],
201 | [23, 45, 15, 28, 46, 16],
202 |
203 | // 32
204 | [17, 145, 115],
205 | [10, 74, 46, 23, 75, 47],
206 | [10, 54, 24, 35, 55, 25],
207 | [19, 45, 15, 35, 46, 16],
208 |
209 | // 33
210 | [17, 145, 115, 1, 146, 116],
211 | [14, 74, 46, 21, 75, 47],
212 | [29, 54, 24, 19, 55, 25],
213 | [11, 45, 15, 46, 46, 16],
214 |
215 | // 34
216 | [13, 145, 115, 6, 146, 116],
217 | [14, 74, 46, 23, 75, 47],
218 | [44, 54, 24, 7, 55, 25],
219 | [59, 46, 16, 1, 47, 17],
220 |
221 | // 35
222 | [12, 151, 121, 7, 152, 122],
223 | [12, 75, 47, 26, 76, 48],
224 | [39, 54, 24, 14, 55, 25],
225 | [22, 45, 15, 41, 46, 16],
226 |
227 | // 36
228 | [6, 151, 121, 14, 152, 122],
229 | [6, 75, 47, 34, 76, 48],
230 | [46, 54, 24, 10, 55, 25],
231 | [2, 45, 15, 64, 46, 16],
232 |
233 | // 37
234 | [17, 152, 122, 4, 153, 123],
235 | [29, 74, 46, 14, 75, 47],
236 | [49, 54, 24, 10, 55, 25],
237 | [24, 45, 15, 46, 46, 16],
238 |
239 | // 38
240 | [4, 152, 122, 18, 153, 123],
241 | [13, 74, 46, 32, 75, 47],
242 | [48, 54, 24, 14, 55, 25],
243 | [42, 45, 15, 32, 46, 16],
244 |
245 | // 39
246 | [20, 147, 117, 4, 148, 118],
247 | [40, 75, 47, 7, 76, 48],
248 | [43, 54, 24, 22, 55, 25],
249 | [10, 45, 15, 67, 46, 16],
250 |
251 | // 40
252 | [19, 148, 118, 6, 149, 119],
253 | [18, 75, 47, 31, 76, 48],
254 | [34, 54, 24, 34, 55, 25],
255 | [20, 45, 15, 61, 46, 16]
256 | ];
257 |
258 | constructor(
259 | private totalCount : number,
260 | private dataCount : number
261 | ) {
262 | }
263 |
264 | public getDataCount() : number {
265 | return this.dataCount;
266 | }
267 |
268 | public getTotalCount() : number {
269 | return this.totalCount;
270 | }
271 |
272 | public static getRSBlocks(
273 | typeNumber : number,
274 | errorCorrectLevel : ErrorCorrectLevel
275 | ) : RSBlock[] {
276 |
277 | var rsBlock = RSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);
278 | var length = rsBlock.length / 3;
279 |
280 | var list : RSBlock[] = [];
281 |
282 | for (var i = 0; i < length; i += 1) {
283 |
284 | var count = rsBlock[i * 3 + 0];
285 | var totalCount = rsBlock[i * 3 + 1];
286 | var dataCount = rsBlock[i * 3 + 2];
287 |
288 | for (var j = 0; j < count; j += 1) {
289 | list.push(new RSBlock(totalCount, dataCount) );
290 | }
291 | }
292 |
293 | return list;
294 | }
295 |
296 | private static getRsBlockTable(
297 | typeNumber : number,
298 | errorCorrectLevel : ErrorCorrectLevel
299 | ) : number[] {
300 |
301 | switch(errorCorrectLevel) {
302 | case ErrorCorrectLevel.L :
303 | return RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
304 | case ErrorCorrectLevel.M :
305 | return RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
306 | case ErrorCorrectLevel.Q :
307 | return RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
308 | case ErrorCorrectLevel.H :
309 | return RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
310 | default :
311 | break;
312 | }
313 |
314 | throw 'tn:' + typeNumber + '/ecl:' + errorCorrectLevel;
315 | }
316 | }
317 | }
318 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/text/createStringToBytes.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | 'use strict';
4 | namespace com.d_project.text {
5 |
6 | import ByteArrayInputStream = com.d_project.io.ByteArrayInputStream;
7 | import Base64DecodeInputStream = com.d_project.io.Base64DecodeInputStream;
8 |
9 | /**
10 | * createStringToBytes
11 | * @author Kazuhiko Arase
12 | * @param unicodeData base64 string of byte array.
13 | * [16bit Unicode],[16bit Bytes], ...
14 | * @param numChars
15 | */
16 | export function createStringToBytes(
17 | unicodeData : string,
18 | numChars : number
19 | ) : (s : string) => number[] {
20 | function toBytes(s : string) : number[] {
21 | var bytes : number[] = [];
22 | for (var i = 0; i < s.length; i += 1) {
23 | bytes.push(s.charCodeAt(i) );
24 | }
25 | return bytes;
26 | }
27 | // create conversion map.
28 | var unicodeMap = function() {
29 | var bin = new Base64DecodeInputStream(
30 | new ByteArrayInputStream(toBytes(unicodeData) ) );
31 | var read = function() {
32 | var b = bin.readByte();
33 | if (b == -1) throw 'eof';
34 | return b;
35 | };
36 | var count = 0;
37 | var unicodeMap : { [ch : string] : number; } = {};
38 | while (true) {
39 | var b0 = bin.readByte();
40 | if (b0 == -1) break;
41 | var b1 = read();
42 | var b2 = read();
43 | var b3 = read();
44 | var k = String.fromCharCode( (b0 << 8) | b1);
45 | var v = (b2 << 8) | b3;
46 | unicodeMap[k] = v;
47 | count += 1;
48 | }
49 | if (count != numChars) {
50 | throw count + '!=' + numChars;
51 | }
52 | return unicodeMap;
53 | }();
54 |
55 | var unknownChar = '?'.charCodeAt(0);
56 |
57 | return function(s : string) : number[] {
58 | var bytes : number[] = [];
59 | for (var i = 0; i < s.length; i += 1) {
60 | var c = s.charCodeAt(i);
61 | if (c < 128) {
62 | bytes.push(c);
63 | } else {
64 | var b = unicodeMap[s.charAt(i)];
65 | if (typeof b == 'number') {
66 | if ( (b & 0xff) == b) {
67 | // 1byte
68 | bytes.push(b);
69 | } else {
70 | // 2bytes
71 | bytes.push(b >>> 8);
72 | bytes.push(b & 0xff);
73 | }
74 | } else {
75 | bytes.push(unknownChar);
76 | }
77 | }
78 | }
79 | return bytes;
80 | };
81 | };
82 | }
83 |
--------------------------------------------------------------------------------
/ts/src/ts/com/d_project/text/stringToBytes_UTF8.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | namespace com.d_project.text {
3 |
4 | /**
5 | * stringToBytes_UTF8
6 | * contributed by elhigu
7 | */
8 | export function stringToBytes_UTF8(s : string) : number[] {
9 | // http://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array
10 | function toUTF8Array(str : string) : number[] {
11 | var utf8 : number[] = [];
12 | for (var i=0; i < str.length; i++) {
13 | var charcode = str.charCodeAt(i);
14 | if (charcode < 0x80) utf8.push(charcode);
15 | else if (charcode < 0x800) {
16 | utf8.push(0xc0 | (charcode >> 6),
17 | 0x80 | (charcode & 0x3f));
18 | }
19 | else if (charcode < 0xd800 || charcode >= 0xe000) {
20 | utf8.push(0xe0 | (charcode >> 12),
21 | 0x80 | ((charcode>>6) & 0x3f),
22 | 0x80 | (charcode & 0x3f));
23 | }
24 | // surrogate pair
25 | else {
26 | i++;
27 | // UTF-16 encodes 0x10000-0x10FFFF by
28 | // subtracting 0x10000 and splitting the
29 | // 20 bits of 0x0-0xFFFFF into two halves
30 | charcode = 0x10000 + (((charcode & 0x3ff)<<10)
31 | | (str.charCodeAt(i) & 0x3ff));
32 | utf8.push(0xf0 | (charcode >>18),
33 | 0x80 | ((charcode>>12) & 0x3f),
34 | 0x80 | ((charcode>>6) & 0x3f),
35 | 0x80 | (charcode & 0x3f));
36 | }
37 | }
38 | return utf8;
39 | }
40 | return toUTF8Array(s);
41 | };
42 | }
43 |
--------------------------------------------------------------------------------
/ts/src/ts/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/ts/src/ts/test.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ///
4 | ///
5 | ///
6 | ///
7 |
8 | 'use strict'
9 | namespace test {
10 |
11 | import QRCode = com.d_project.qrcode.QRCode;
12 | import ErrorCorrectLevel = com.d_project.qrcode.ErrorCorrectLevel;
13 | import QRNumber = com.d_project.qrcode.QRNumber;
14 | import QRAlphaNum = com.d_project.qrcode.QRAlphaNum;
15 | import QR8BitByte = com.d_project.qrcode.QR8BitByte;
16 | import QRKanji = com.d_project.qrcode.QRKanji;
17 |
18 | export function run() : void {
19 |
20 | // uncomment if UTF-8 support is required.
21 | //QRCode.stringToBytes = com.d_project.text.stringToBytes_UTF8;
22 |
23 | var qr = new QRCode();
24 | qr.setTypeNumber(5);
25 | qr.setErrorCorrectLevel(ErrorCorrectLevel.L);
26 | qr.addData(new QRNumber('0123') ); // Number only
27 | qr.addData(new QRAlphaNum('AB5678CD') ); // Alphabet and Number
28 | qr.addData(new QR8BitByte('[8BitByte :)]') ); // most useful for usual purpose.
29 | qr.addData('[here is 8BitByte too]');
30 | qr.addData(new QRKanji('漢字') ); // Kanji(SJIS) only
31 | qr.make();
32 |
33 | // img
34 | var img = document.createElement('img');
35 | img.setAttribute('src', qr.toDataURL() );
36 | document.body.appendChild(img);
37 |
38 | // canvas
39 | document.body.appendChild(createCanvas(qr, 2) );
40 | }
41 |
42 | function createCanvas(qr : QRCode, cellSize = 2, margin = cellSize * 4) {
43 |
44 | var canvas = document.createElement('canvas');
45 | var size = qr.getModuleCount() * cellSize + margin * 2;
46 | canvas.width = size;
47 | canvas.height = size;
48 | var ctx = canvas.getContext('2d');
49 |
50 | // fill background
51 | ctx.fillStyle = '#ffffff';
52 | ctx.fillRect(0, 0, size, size);
53 |
54 | // draw cells
55 | ctx.fillStyle = '#000000';
56 | for (var row = 0; row < qr.getModuleCount(); row += 1) {
57 | for (var col = 0; col < qr.getModuleCount(); col += 1) {
58 | if (qr.isDark(row, col) ) {
59 | ctx.fillRect(
60 | col * cellSize + margin,
61 | row * cellSize + margin,
62 | cellSize, cellSize);
63 | }
64 | }
65 | }
66 | return canvas;
67 | }
68 | }
69 |
70 | window.onload = function() {
71 | test.run();
72 | };
73 |
--------------------------------------------------------------------------------