qrencoder 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|