qrencoder 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +5 -0
- data/{README.txt → README.rdoc} +41 -19
- data/ext/qrencoder_ext/extconf.rb +7 -0
- data/ext/qrencoder_ext/qrencoder_ext.c +273 -0
- data/lib/qrencoder.rb +54 -268
- data/lib/qrencoder/qrcode.rb +54 -0
- data/lib/qrencoder/qrencoder_ext.bundle +0 -0
- data/lib/qrencoder/version.rb +3 -0
- data/spec/qrcode_spec.rb +204 -0
- data/spec/qrencoder_spec.rb +69 -0
- data/spec/spec_helper.rb +8 -0
- metadata +140 -59
- data/Manifest.txt +0 -7
- data/Rakefile +0 -19
- data/bin/qrencoder +0 -0
- data/test/test_qrencoder.rb +0 -99
data/History.txt
CHANGED
data/{README.txt → README.rdoc}
RENAMED
@@ -30,31 +30,26 @@ All of these in a square that may range from 21 to 177 pixels a side (there are
|
|
30
30
|
multiple levels of error correction are possible which might also influence the
|
31
31
|
final size.
|
32
32
|
|
33
|
-
==
|
34
|
-
|
35
|
-
* This gem requires you to build and install an external C library
|
36
|
-
* The QREncode lib this GEM is built around is NOT thread-safe!
|
33
|
+
== USAGE:
|
37
34
|
|
38
|
-
|
35
|
+
Basic usage is as follows:
|
39
36
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
37
|
+
text = "Some string"
|
38
|
+
qrcode = QREncoder.encode(text) #=> #<QREncoder::QRCode:0x1003710d0>
|
39
|
+
puts "#{qrcode.version}" #=> 7
|
40
|
+
puts "#{qrcode.width}" #=> 34
|
41
|
+
qrcode.save_png("/tmp/foo.png")
|
45
42
|
|
46
|
-
|
47
|
-
puts "#{img.version}" #=> 7
|
48
|
-
puts "#{img.width}" #=> 34
|
49
|
-
img.save_png("/tmp/foo.png")
|
50
|
-
|
51
|
-
You can retrieve the pixels of the output image directly or use the included
|
43
|
+
You can retrieve the pixels of the QRCode object directly or use the included
|
52
44
|
methods to save a PNG file directly.
|
53
45
|
|
46
|
+
See the rdocs[http://rdoc.info/github/harrisj/qrencoder] for options you can
|
47
|
+
pass to <tt>QREncoder#encode</tt>.
|
48
|
+
|
54
49
|
== REQUIREMENTS:
|
55
50
|
|
56
51
|
This gem requires you to build the C library lib <tt>libqrcode.a</tt> available
|
57
|
-
from http://megaui.net/fukuchi/works/qrencode/index.en.html.
|
52
|
+
from http://megaui.net/fukuchi/works/qrencode/index.en.html.
|
58
53
|
|
59
54
|
Normally, the build process also expects you to install <tt>libpng</tt>, but
|
60
55
|
this is only used for the <tt>qrenc</tt> command-line utility and can be avoided
|
@@ -69,10 +64,37 @@ This gem also requires the following gems to be installed:
|
|
69
64
|
* ruby-inline
|
70
65
|
* png
|
71
66
|
|
72
|
-
==
|
67
|
+
== INSTALLATION:
|
73
68
|
|
74
69
|
* First build the <tt>libqrencode</tt> library following the instructions above.
|
75
|
-
* Then <tt>sudo gem install qrencoder
|
70
|
+
* Then <tt>[sudo] gem install qrencoder</tt>
|
71
|
+
|
72
|
+
== DEVELOPMENT AND CONTRIBUTING:
|
73
|
+
|
74
|
+
This project uses Bundler and its own gemspec for dependency management. To get
|
75
|
+
started, just clone the repo and run:
|
76
|
+
|
77
|
+
gem install bundler
|
78
|
+
bundle install
|
79
|
+
rake
|
80
|
+
|
81
|
+
The default Rake task will compile the C component and run the specs. If it
|
82
|
+
fails to build, make sure that you have libqrencode installed properly.
|
83
|
+
|
84
|
+
Please send pull requests. Topic branches are preferred. New features will not
|
85
|
+
be accepted without corresponding tests.
|
86
|
+
|
87
|
+
== FEATURES/PROBLEMS:
|
88
|
+
|
89
|
+
* This gem requires you to build and install an external C library
|
90
|
+
* The QREncode lib this GEM is built around is NOT thread-safe!
|
91
|
+
|
92
|
+
== CONTRIBUTORS:
|
93
|
+
|
94
|
+
* Jacob Harris (harrisj)
|
95
|
+
* Joshua Davey (jgdavey)
|
96
|
+
* Joseph Holsten
|
97
|
+
* Wesley Moore (wezm)
|
76
98
|
|
77
99
|
== QRCODE LICENSE:
|
78
100
|
|
@@ -0,0 +1,273 @@
|
|
1
|
+
#include "qrencode.h"
|
2
|
+
#include "ruby.h"
|
3
|
+
|
4
|
+
VALUE mQREncoder;
|
5
|
+
VALUE cQRCode;
|
6
|
+
|
7
|
+
static void qrcode_free(void *p) {
|
8
|
+
QRcode *qrcode = (QRcode *) p;
|
9
|
+
QRcode_free(qrcode);
|
10
|
+
}
|
11
|
+
|
12
|
+
/*
|
13
|
+
* call-seq:
|
14
|
+
* width
|
15
|
+
*
|
16
|
+
* Width of the symbol in modules. This value usually corresponds to 1 module
|
17
|
+
* is 1 pixel, but you could conceivably scale it up if you wanted to.
|
18
|
+
*/
|
19
|
+
static VALUE _width(VALUE self) {
|
20
|
+
QRcode *qrcode;
|
21
|
+
Data_Get_Struct(self, QRcode, qrcode);
|
22
|
+
return INT2FIX(qrcode->width);
|
23
|
+
}
|
24
|
+
|
25
|
+
|
26
|
+
/*
|
27
|
+
* call-seq:
|
28
|
+
* version
|
29
|
+
*
|
30
|
+
* Version of the symbol. A QR Code version indicates the size of the 2-D
|
31
|
+
* barcode in modules. See +qrencode_string+ for a more detailed description of
|
32
|
+
* the version. Note that the version returned might be larger than the version
|
33
|
+
* specified for an encode_string if the requested version is for a barcode too
|
34
|
+
* small to encode the data.
|
35
|
+
*/
|
36
|
+
static VALUE _version(VALUE self) {
|
37
|
+
QRcode *qrcode;
|
38
|
+
Data_Get_Struct(self, QRcode, qrcode);
|
39
|
+
return INT2FIX(qrcode->version);
|
40
|
+
}
|
41
|
+
|
42
|
+
/*
|
43
|
+
* call-seq:
|
44
|
+
* data
|
45
|
+
*
|
46
|
+
* Returns the raw data of the QRcode within a single array of width*width
|
47
|
+
* elements. Each item is a byte of data of which only the least significant
|
48
|
+
* bit is the pixel. The full use of each bit from Least Significant to Most is
|
49
|
+
* as follows
|
50
|
+
*
|
51
|
+
* - 1=black / 0=white
|
52
|
+
* - data and ecc code area
|
53
|
+
* - format information
|
54
|
+
* - version information
|
55
|
+
* - timing pattern
|
56
|
+
* - alignment pattern
|
57
|
+
* - finder pattern and separator
|
58
|
+
* - non-data modules (format, timing, etc.)
|
59
|
+
*
|
60
|
+
* This structure allows the QRcode spec to store multiple types of information
|
61
|
+
* within the allocated output buffers, but you usually only care about the pixel
|
62
|
+
* color. For those cases, just use the +pixels+ or +points+ methods.
|
63
|
+
*/
|
64
|
+
static VALUE _data(VALUE self) {
|
65
|
+
QRcode *qrcode;
|
66
|
+
VALUE out;
|
67
|
+
unsigned char *p, b;
|
68
|
+
int i, max;
|
69
|
+
|
70
|
+
Data_Get_Struct(self, QRcode, qrcode);
|
71
|
+
p = qrcode->data;
|
72
|
+
max = qrcode->width * qrcode->width;
|
73
|
+
out = rb_ary_new2(max);
|
74
|
+
|
75
|
+
for (i=0; i < max; i++) {
|
76
|
+
b = *p;
|
77
|
+
rb_ary_push(out, INT2FIX(b));
|
78
|
+
p++;
|
79
|
+
}
|
80
|
+
|
81
|
+
return out;
|
82
|
+
}
|
83
|
+
|
84
|
+
/*
|
85
|
+
* call-seq:
|
86
|
+
* pixels
|
87
|
+
*
|
88
|
+
* Returns the QRcode as an array of rows where each item in a row represents
|
89
|
+
* the value of the pixel (1 = black, 0 = white)
|
90
|
+
*/
|
91
|
+
static VALUE _pixels(VALUE self) {
|
92
|
+
QRcode *qrcode;
|
93
|
+
VALUE out, row;
|
94
|
+
unsigned char *p;
|
95
|
+
int x, y, bit;
|
96
|
+
|
97
|
+
Data_Get_Struct(self, QRcode, qrcode);
|
98
|
+
p = qrcode->data;
|
99
|
+
out = rb_ary_new2(qrcode->width);
|
100
|
+
|
101
|
+
for (y=0; y < qrcode->width; y++) {
|
102
|
+
row = rb_ary_new2(qrcode->width);
|
103
|
+
|
104
|
+
for (x=0; x < qrcode->width; x++) {
|
105
|
+
bit = *p & 1;
|
106
|
+
rb_ary_push(row, INT2FIX(bit));
|
107
|
+
p++;
|
108
|
+
}
|
109
|
+
|
110
|
+
rb_ary_push(out, row);
|
111
|
+
}
|
112
|
+
|
113
|
+
return out;
|
114
|
+
}
|
115
|
+
|
116
|
+
/*
|
117
|
+
* call-seq:
|
118
|
+
* points
|
119
|
+
*
|
120
|
+
* Returns the black pixels of the encoded image as an array of coordinate pairs.
|
121
|
+
*/
|
122
|
+
static VALUE _points(VALUE self) {
|
123
|
+
QRcode *qrcode;
|
124
|
+
VALUE out, point;
|
125
|
+
unsigned char *p;
|
126
|
+
int x, y, bit;
|
127
|
+
|
128
|
+
Data_Get_Struct(self, QRcode, qrcode);
|
129
|
+
p = qrcode->data;
|
130
|
+
out = rb_ary_new2(qrcode->width);
|
131
|
+
|
132
|
+
for (y=0; y < qrcode->width; y++) {
|
133
|
+
for (x=0; x < qrcode->width; x++) {
|
134
|
+
bit = *p & 1;
|
135
|
+
|
136
|
+
if (bit) {
|
137
|
+
point = rb_ary_new2(2);
|
138
|
+
rb_ary_push(point, INT2FIX(x));
|
139
|
+
rb_ary_push(point, INT2FIX(y));
|
140
|
+
rb_ary_push(out, point);
|
141
|
+
}
|
142
|
+
|
143
|
+
p++;
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
return out;
|
148
|
+
}
|
149
|
+
|
150
|
+
/* Handles +clone+ and +dup+ */
|
151
|
+
static VALUE qr_init_copy(VALUE copy, VALUE orig) {
|
152
|
+
QRcode *copy_qrcode;
|
153
|
+
QRcode *orig_qrcode;
|
154
|
+
if (copy == orig)
|
155
|
+
return copy;
|
156
|
+
|
157
|
+
Data_Get_Struct(orig, QRcode, orig_qrcode);
|
158
|
+
Data_Get_Struct(copy, QRcode, copy_qrcode);
|
159
|
+
MEMCPY(copy_qrcode, orig_qrcode, QRcode, 1);
|
160
|
+
|
161
|
+
/* Code will be freed by original object */
|
162
|
+
RDATA(copy)->dfree = NULL;
|
163
|
+
|
164
|
+
return copy;
|
165
|
+
}
|
166
|
+
|
167
|
+
/*
|
168
|
+
* call-seq:
|
169
|
+
* new(string, version, eclevel, mode, case_sensitive)
|
170
|
+
*
|
171
|
+
* Encodes a QR code from a string.
|
172
|
+
*
|
173
|
+
* There are 5 required arguments:
|
174
|
+
*
|
175
|
+
* [string] the string to encode
|
176
|
+
* [version] the version of the QR Code
|
177
|
+
* [error correction level] an integer representing an error correction level
|
178
|
+
* [encoding mode] an integer representing the encoding mode
|
179
|
+
* [case sensitivity] 1 (case sensitive) or 0 (case insensitive)
|
180
|
+
*
|
181
|
+
* == Version
|
182
|
+
*
|
183
|
+
* What is the version? Each QRCode is made up of <b>modules</b> which are the
|
184
|
+
* basic display element of a QRCode and may be made up of 1 or more pixels
|
185
|
+
* (here, it's just 1 module is 1 pixel). Version 1 is a 21x21 module square,
|
186
|
+
* while the maximum version 40 is 177x177 modules. The full module reference
|
187
|
+
* is here http://www.denso-wave.com/qrcode/vertable1-e.html
|
188
|
+
*
|
189
|
+
* Should you encode more text than can fit in a module, the encoder will scale
|
190
|
+
* up to the smallest version able to contain your data. Unless you want to
|
191
|
+
* specifically fix your barcode to a certain version, it's fine to just set
|
192
|
+
* the version argument to 1 and let the algorithm figure out the proper size.
|
193
|
+
*
|
194
|
+
* == Error correction
|
195
|
+
*
|
196
|
+
* The following four constants can be specified for error correction levels, each
|
197
|
+
* specified with the maximum approximate error rate they can compensate for, as
|
198
|
+
* well as the maximum capacity of an 8-bit data QR Code with the error encoding:
|
199
|
+
*
|
200
|
+
* - <tt>QR_ECLEVEL_L</tt> - 7%/2953 [default]
|
201
|
+
* - <tt>QR_ECLEVEL_M</tt> - 15%/2331
|
202
|
+
* - <tt>QR_ECLEVEL_Q</tt> - 25%/1663
|
203
|
+
* - <tt>QR_ECLEVEL_H</tt> - 30%/1273
|
204
|
+
*
|
205
|
+
* Higher error rates are suitable for applications where the QR Code is likely
|
206
|
+
* to be smudged or damaged, but as is apparent here, they can radically reduce
|
207
|
+
* the maximum data capacity of a QR Code.
|
208
|
+
*
|
209
|
+
* == Encoding mode
|
210
|
+
*
|
211
|
+
* There are 4 possible encodings for a QR Code which can modify the maximum
|
212
|
+
* data capacity. These are specified with four possible Constants, each
|
213
|
+
* listed here with the maximum capacity available for that encoding at the
|
214
|
+
* lowest error correction rate.
|
215
|
+
*
|
216
|
+
* - <tt>QR_MODE_NUM</tt> - Numeric/7089
|
217
|
+
* - <tt>QR_MODE_AN</tt> - Alphanumeric/4296
|
218
|
+
* - <tt>QR_MODE_8</tt> - 8-bit ASCII/2953 [default]
|
219
|
+
* - <tt>QR_MODE_KANJI</tt> - Kanji (JIS-1 & 2)/1817
|
220
|
+
*
|
221
|
+
* Note that the QR Code specification seemingly predates the rise and triumph
|
222
|
+
* of UTF-8, and the specification makes no requirement that writers and
|
223
|
+
* readers use ISO-8859-1 or UTF-8 or whatever to interpret the data in a
|
224
|
+
* barcode. If you encode in UTF-8, it might be read as ISO-8859-1 or not.
|
225
|
+
*
|
226
|
+
* == Case sensitivity
|
227
|
+
*
|
228
|
+
* Encoding can either be case sensitive (1) or not (0). Without case
|
229
|
+
* sensitivity turned on, many decoders will view all alphabetic characters as
|
230
|
+
* uppercase.
|
231
|
+
*/
|
232
|
+
static VALUE qr_initialize(VALUE self, VALUE _string, VALUE _version, VALUE _eclevel, VALUE _hint, VALUE _casesensitive) {
|
233
|
+
const char *string = StringValuePtr(_string);
|
234
|
+
int version = FIX2INT(_version);
|
235
|
+
int eclevel = FIX2INT(_eclevel);
|
236
|
+
int hint = FIX2INT(_hint);
|
237
|
+
int casesensitive = FIX2INT(_casesensitive);
|
238
|
+
|
239
|
+
QRcode *code = QRcode_encodeString(string, version, eclevel, hint, casesensitive);
|
240
|
+
|
241
|
+
if (DATA_PTR(self)) {
|
242
|
+
QRcode_free(DATA_PTR(self));
|
243
|
+
DATA_PTR(self) = NULL;
|
244
|
+
}
|
245
|
+
|
246
|
+
DATA_PTR(self) = code;
|
247
|
+
return self;
|
248
|
+
}
|
249
|
+
|
250
|
+
/* Allocate memory */
|
251
|
+
static VALUE qr_alloc(VALUE klass) {
|
252
|
+
QRcode *code;
|
253
|
+
VALUE obj = Data_Make_Struct(klass, QRcode, NULL, qrcode_free, code);
|
254
|
+
return obj;
|
255
|
+
}
|
256
|
+
|
257
|
+
void Init_qrencoder_ext()
|
258
|
+
{
|
259
|
+
mQREncoder = rb_define_module("QREncoder");
|
260
|
+
cQRCode = rb_define_class_under(mQREncoder, "QRCode", rb_cObject);
|
261
|
+
|
262
|
+
rb_define_method(cQRCode, "initialize_copy", qr_init_copy, 1);
|
263
|
+
rb_define_method(cQRCode, "initialize", qr_initialize, 5);
|
264
|
+
rb_define_alloc_func(cQRCode, qr_alloc);
|
265
|
+
|
266
|
+
rb_define_method(cQRCode, "width", _width, 0);
|
267
|
+
rb_define_method(cQRCode, "version", _version, 0);
|
268
|
+
rb_define_method(cQRCode, "data", _data, 0);
|
269
|
+
rb_define_method(cQRCode, "pixels", _pixels, 0);
|
270
|
+
rb_define_method(cQRCode, "points", _points, 0);
|
271
|
+
|
272
|
+
rb_define_alias(cQRCode, "height", "width");
|
273
|
+
}
|
data/lib/qrencoder.rb
CHANGED
@@ -1,282 +1,68 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
require '
|
1
|
+
require 'qrencoder/version'
|
2
|
+
require 'qrencoder/qrencoder_ext'
|
3
|
+
require 'qrencoder/qrcode'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
# Encoding modes
|
5
|
+
module QREncoder
|
6
|
+
# Numeric-only encoding mode
|
9
7
|
QR_MODE_NUM = 0
|
10
|
-
QR_MODE_AN = 1
|
11
|
-
QR_MODE_8 = 2
|
12
|
-
QR_MODE_KANJI = 3
|
13
|
-
|
14
|
-
# Error correction
|
15
|
-
QR_ECLEVEL_L = 0
|
16
|
-
QR_ECLEVEL_M = 1
|
17
|
-
QR_ECLEVEL_Q = 2
|
18
|
-
QR_ECLEVEL_H = 3
|
19
|
-
|
20
|
-
##
|
21
|
-
# Version of the symbol. A QR Code version indicates the size of the 2-D
|
22
|
-
# barcode in modules. See #qrencode_string for a more detailed description of
|
23
|
-
# the version. Note that the version returned might be larger than the version
|
24
|
-
# specified for an encode_string if the requested version is for a barcode too
|
25
|
-
# small to encode the data.
|
26
|
-
def version; end;
|
27
|
-
|
28
|
-
##
|
29
|
-
# Width of the symbol in modules. This value usually corresponds to 1 module
|
30
|
-
# is 1 pixel, but you could conceivably scale it up if you wanted to.
|
31
|
-
def width; end;
|
32
8
|
|
33
|
-
|
34
|
-
|
35
|
-
# elements. Each item is a byte of data of which only the least significant
|
36
|
-
# bit is the pixel. The full use of each bit from Least Significant to Most is
|
37
|
-
# as follows
|
38
|
-
#
|
39
|
-
# * 1=black/0=white
|
40
|
-
# * data and ecc code area
|
41
|
-
# * format information
|
42
|
-
# * version information
|
43
|
-
# * timing pattern
|
44
|
-
# * alignment pattern
|
45
|
-
# * finder pattern and separator
|
46
|
-
# * non-data modules (format, timing, etc.)
|
47
|
-
#
|
48
|
-
# This structure allows the QRcode spec to store multiple types of information
|
49
|
-
# within the allocated output buffers, but you usually only care about the pixel
|
50
|
-
# color. For those cases, just use the #pixels or #points methods.
|
51
|
-
def data; end;
|
52
|
-
|
53
|
-
##
|
54
|
-
# Returns the QRcode as an array of rows where each item in a row represents
|
55
|
-
# the value of the pixel (1=black, 0=white)
|
56
|
-
def pixels; end;
|
9
|
+
# Alphanumeric-only encoding mode
|
10
|
+
QR_MODE_AN = 1
|
57
11
|
|
58
|
-
|
59
|
-
|
60
|
-
def points; end;
|
61
|
-
|
62
|
-
##
|
63
|
-
# Encodes a QR code from a string. This version of the method assumes the
|
64
|
-
# input data is 8-bit ASCII and that you want the most basic error correction.
|
65
|
-
# For more detailed control over those parameters, use #encode_string_ex. This
|
66
|
-
# method takes 2 arguments: a string to encode and a QRCode <tt>version</tt>
|
67
|
-
# which essentially determines the size of the QRCode.
|
68
|
-
#
|
69
|
-
# What is the version? Each QRCode is made up
|
70
|
-
# of <b>modules</b> which are the basic display element of a QRCode and may
|
71
|
-
# be made up of 1 or more pixels (here, it's just 1 module is 1 pixel).
|
72
|
-
# Version 1 is a 21x21
|
73
|
-
# module square, while the maximum version 40 is 177x177 modules. The full
|
74
|
-
# module reference is here http://www.denso-wave.com/qrcode/vertable1-e.html
|
75
|
-
#
|
76
|
-
# Should you encode more text than can fit in a module, the encoder will scale
|
77
|
-
# up to the smallest version able to contain your data. Unless you want to
|
78
|
-
# specifically fix your barcode to a certain version, it's fine to just set
|
79
|
-
# the version argument to 1 and let #encode_string figure out the proper size.
|
80
|
-
def encode_string; end;
|
81
|
-
|
82
|
-
##
|
83
|
-
# This function is similar in purpose to #encode_string, but it allows you to
|
84
|
-
# explicitly specify the encoding and error correction level. There are 4
|
85
|
-
# arguments to this function:
|
86
|
-
#
|
87
|
-
# * <tt>string</tt> the string to encode
|
88
|
-
# * <tt>version</tt> the version of the QR Code (see #encode_string for explanation)
|
89
|
-
# * <tt>error correction level</tt>
|
90
|
-
# * <tt>encoding mode</tt>
|
91
|
-
#
|
92
|
-
# The following four Constants can be specified for error correction levels, each
|
93
|
-
# specified with the maximum approximate error rate they can compensate for, as
|
94
|
-
# well as the maximum capacity of an 8-bit data QR Code with the error encoding:
|
95
|
-
#
|
96
|
-
# * <tt>QR_ECLEVEL_L</tt> - 7%/2953 [default]
|
97
|
-
# * <tt>QR_ECLEVEL_M</tt> - 15%/2331
|
98
|
-
# * <tt>QR_ECLEVEL_Q</tt> - 25%/1663
|
99
|
-
# * <tt>QR_ECLEVEL_H</tt> - 30%/1273
|
100
|
-
#
|
101
|
-
# Higher error rates are suitable for applications where the QR Code is likely
|
102
|
-
# to be smudged or damaged, but as is apparent here, they can radically reduce
|
103
|
-
# the maximum data capacity of a QR Code.
|
104
|
-
#
|
105
|
-
# There are also 4 possible encodings for a QR Code which can modify the
|
106
|
-
# maximum data capacity. These are specified with four possible Constants, each
|
107
|
-
# listed here with the maximum capacity available for that encoding at the lowest
|
108
|
-
# error correction rate.
|
109
|
-
#
|
110
|
-
# * <tt>QR_MODE_NUM</tt> - Numeric/7089
|
111
|
-
# * <tt>QR_MODE_AN</tt> - Alphanumeric/4296
|
112
|
-
# * <tt>QR_MODE_8</tt> - 8-bit ASCII/2953 [default]
|
113
|
-
# * <tt>QR_MODE_KANJI</tt> - Kanji (JIS-1 & 2)/1817
|
114
|
-
#
|
115
|
-
# Note that the QR Code specification seemingly predates the rise and triumph
|
116
|
-
# of UTF-8, and the specification makes no requirement that writers and readers
|
117
|
-
# use ISO-8859-1 or UTF-8 or whatever to interpret the data in a barcode. If you
|
118
|
-
# encode in UTF-8, it might be read as ISO-8859-1 or not.
|
119
|
-
def encode_string_ex; end;
|
120
|
-
|
121
|
-
# now for the inlines
|
122
|
-
inline do |builder|
|
123
|
-
builder.add_link_flags "-lqrencode"
|
124
|
-
builder.include '"qrencode.h"'
|
12
|
+
# 8-bit ASCII encoding mode
|
13
|
+
QR_MODE_8 = 2
|
125
14
|
|
126
|
-
|
127
|
-
|
128
|
-
QRcode *qrcode = (QRcode *) p;
|
129
|
-
QRcode_free(qrcode);
|
130
|
-
}
|
131
|
-
END
|
132
|
-
|
133
|
-
builder.c <<-"END"
|
134
|
-
int width() {
|
135
|
-
QRcode *qrcode;
|
136
|
-
Data_Get_Struct(self, QRcode, qrcode);
|
137
|
-
return qrcode->width;
|
138
|
-
}
|
139
|
-
END
|
140
|
-
|
141
|
-
builder.c <<-"END"
|
142
|
-
int version() {
|
143
|
-
QRcode *qrcode;
|
144
|
-
Data_Get_Struct(self, QRcode, qrcode);
|
145
|
-
return qrcode->version;
|
146
|
-
}
|
147
|
-
END
|
148
|
-
|
149
|
-
builder.c <<-"END"
|
150
|
-
VALUE data() {
|
151
|
-
QRcode *qrcode;
|
152
|
-
VALUE out;
|
153
|
-
unsigned char *p, b;
|
154
|
-
int i, max;
|
155
|
-
|
156
|
-
Data_Get_Struct(self, QRcode, qrcode);
|
157
|
-
p = qrcode->data;
|
158
|
-
max = qrcode->width * qrcode->width;
|
159
|
-
out = rb_ary_new2(max);
|
160
|
-
|
161
|
-
for (i=0; i < max; i++) {
|
162
|
-
b = *p;
|
163
|
-
rb_ary_push(out, INT2FIX(b));
|
164
|
-
p++;
|
165
|
-
}
|
166
|
-
|
167
|
-
return out;
|
168
|
-
}
|
169
|
-
END
|
170
|
-
|
171
|
-
builder.c <<-"END"
|
172
|
-
VALUE pixels() {
|
173
|
-
QRcode *qrcode;
|
174
|
-
VALUE out, row;
|
175
|
-
unsigned char *p;
|
176
|
-
int x, y, bit;
|
177
|
-
|
178
|
-
Data_Get_Struct(self, QRcode, qrcode);
|
179
|
-
p = qrcode->data;
|
180
|
-
out = rb_ary_new2(qrcode->width);
|
181
|
-
|
182
|
-
for (y=0; y < qrcode->width; y++) {
|
183
|
-
row = rb_ary_new2(qrcode->width);
|
15
|
+
# Kanji encoding mode
|
16
|
+
QR_MODE_KANJI = 3
|
184
17
|
|
185
|
-
|
186
|
-
|
187
|
-
rb_ary_push(row, INT2FIX(bit));
|
188
|
-
p++;
|
189
|
-
}
|
18
|
+
# Low error correction
|
19
|
+
QR_ECLEVEL_L = 0
|
190
20
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
return out;
|
195
|
-
}
|
196
|
-
END
|
197
|
-
|
198
|
-
builder.c <<-"END"
|
199
|
-
VALUE points() {
|
200
|
-
QRcode *qrcode;
|
201
|
-
VALUE out, point;
|
202
|
-
unsigned char *p;
|
203
|
-
int x, y, bit;
|
21
|
+
# Medium error correction
|
22
|
+
QR_ECLEVEL_M = 1
|
204
23
|
|
205
|
-
|
206
|
-
|
207
|
-
out = rb_ary_new2(qrcode->width);
|
208
|
-
|
209
|
-
for (y=0; y < qrcode->width; y++) {
|
210
|
-
for (x=0; x < qrcode->width; x++) {
|
211
|
-
bit = *p & 1;
|
24
|
+
# Medium-high error correction
|
25
|
+
QR_ECLEVEL_Q = 2
|
212
26
|
|
213
|
-
|
214
|
-
|
215
|
-
rb_ary_push(point, INT2FIX(x));
|
216
|
-
rb_ary_push(point, INT2FIX(y));
|
217
|
-
rb_ary_push(out, point);
|
218
|
-
}
|
27
|
+
# High error correction
|
28
|
+
QR_ECLEVEL_H = 3
|
219
29
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
30
|
+
# Encode a string, return a QRCode object
|
31
|
+
#
|
32
|
+
# This method takes 2 arguments: the string you wish to encode, and a hash of
|
33
|
+
# options. The options are as follows:
|
34
|
+
#
|
35
|
+
# [:version] An integer representing the minimum QRCode version (default: +1+)
|
36
|
+
# [:correction] The amount of error correction to apply. One of +:low+, +:medium+, +:high+. (default: +:low+)
|
37
|
+
# [:mode] The encoding mode to use. Must be one of +:numeric+, +:alphanumeric+, +:ascii+, +:kanji+. (default: +:ascii+)
|
38
|
+
# [:case_sensitive] Set to +false+ if case does not matter. (default: +true+)
|
39
|
+
#
|
40
|
+
# For more information about what each of these modes and correction levels
|
41
|
+
# mean, see QRCode.new
|
42
|
+
#
|
43
|
+
def self.encode(string, options={})
|
44
|
+
version = options[:version] || 1
|
45
|
+
correction = corrections[options[:correction] || :low]
|
46
|
+
mode = modes[options[:mode] || :ascii]
|
47
|
+
case_sensitive = options[:case_sensitive] == false ? 0 : 1
|
48
|
+
QRCode.new(string, version, correction, mode, case_sensitive)
|
49
|
+
end
|
238
50
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
return Data_Wrap_Struct(klass, NULL, qrcode_free, code);
|
247
|
-
}
|
248
|
-
END
|
249
|
-
|
250
|
-
# builder.c <<-"END"
|
251
|
-
# VALUE encode_data_ex(const char *data, int len, int version, int eclevel, int mode) {
|
252
|
-
# QRcode *code;
|
253
|
-
# QRinput *input;
|
254
|
-
#
|
255
|
-
# input = QRinput_new();
|
256
|
-
# QRinput_append(input, mode, data, len);
|
257
|
-
# code = QRcode_encode(input, version, eclevel);
|
258
|
-
# Qrinput_free(input);
|
259
|
-
# return Data_Wrap_Struct(CLASS_OF(self), NULL, qrcode_free, code);
|
260
|
-
# }
|
261
|
-
# END
|
262
|
-
end
|
263
|
-
|
264
|
-
##
|
265
|
-
# Height of the symbol. Since QR Codes are square, this is the same as the
|
266
|
-
# width but this alias is provided if you want to avoid confusion.
|
267
|
-
alias :height :width
|
268
|
-
|
269
|
-
##
|
270
|
-
# Save the QRcode to a PNG file. You can also specify a margin in pixels around
|
271
|
-
# the image, although the specification requests it should be at least 4 px.
|
272
|
-
def save_png(path, margin=4)
|
273
|
-
canvas = PNG::Canvas.new width + (2*margin), width+(2*margin)
|
51
|
+
def self.corrections
|
52
|
+
{
|
53
|
+
:low => QR_ECLEVEL_L,
|
54
|
+
:medium => QR_ECLEVEL_M,
|
55
|
+
:high => QR_ECLEVEL_H
|
56
|
+
}
|
57
|
+
end
|
274
58
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
59
|
+
def self.modes
|
60
|
+
{
|
61
|
+
:numeric => QR_MODE_NUM,
|
62
|
+
:alphanumeric => QR_MODE_AN,
|
63
|
+
:ascii => QR_MODE_8,
|
64
|
+
:kanji => QR_MODE_KANJI
|
65
|
+
}
|
281
66
|
end
|
67
|
+
|
282
68
|
end
|