qrencoder 1.3.4 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +13 -0
- data/README.rdoc +9 -9
- data/ext/qrencoder_ext/qrencoder_ext.c +13 -1
- data/lib/qrencoder.rb +2 -1
- data/lib/qrencoder/png.rb +51 -0
- data/lib/qrencoder/qrcode.rb +3 -24
- data/lib/qrencoder/version.rb +1 -1
- data/spec/integration_spec.rb +32 -4
- data/spec/qrencoder/png_spec.rb +107 -0
- data/spec/{qrcode_spec.rb → qrencoder/qrcode_spec.rb} +5 -5
- data/spec/qrencoder_spec.rb +1 -1
- metadata +9 -6
data/History.txt
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
== 1.4.0 / 2011-10-02
|
2
|
+
|
3
|
+
* API changes
|
4
|
+
* PNG is now a full-fledged object to allow further
|
5
|
+
customization. See chunky_png for more details.
|
6
|
+
* Update chunky_png dependency to allow newest versions
|
7
|
+
|
8
|
+
* Bugfixes
|
9
|
+
* alphanumeric mode was not working correctly
|
10
|
+
* numeric mode segfaulted when passed an integer
|
11
|
+
* Passing an invalid string now raises an ArgumentError
|
12
|
+
rather than segfaulting
|
13
|
+
|
1
14
|
== 1.3.4 / 2011-03-08
|
2
15
|
|
3
16
|
* 1 Minor enhancement
|
data/README.rdoc
CHANGED
@@ -12,12 +12,12 @@ like the following:
|
|
12
12
|
|
13
13
|
http://www.denso-wave.com/qrcode/images/qrcode.gif
|
14
14
|
|
15
|
-
The specification for QR
|
15
|
+
The specification for QR Code is readable at
|
16
16
|
http://www.denso-wave.com/qrcode/index-e.html. QR Code is not the only 2-D
|
17
17
|
barcode standard in existence, and it is in wider use in Japan than elsewhere.
|
18
18
|
Notable competitors include PDF417, Semacode/DataMatrix, and Maxi Code (seen on
|
19
19
|
UPS labels) in North America; ShotCode in the UK; and an additional format used
|
20
|
-
in Korea. All vary in look and capacity, but QR
|
20
|
+
in Korea. All vary in look and capacity, but QR Code has one of the largest
|
21
21
|
information densities and capacities among them with the following maximum data
|
22
22
|
|
23
23
|
* Numeric 7,089
|
@@ -40,7 +40,7 @@ Basic usage is as follows:
|
|
40
40
|
puts "#{qrcode.width}" #=> 34
|
41
41
|
qrcode.save_png("/tmp/foo.png")
|
42
42
|
|
43
|
-
You can retrieve the pixels of the
|
43
|
+
You can retrieve the pixels of the QR Code object directly or use the included
|
44
44
|
methods to save a PNG file directly.
|
45
45
|
|
46
46
|
See the rdocs[http://rdoc.info/github/harrisj/qrencoder] for options you can
|
@@ -53,13 +53,13 @@ from http://megaui.net/fukuchi/works/qrencode/index.en.html.
|
|
53
53
|
|
54
54
|
Installation is usually as simple as:
|
55
55
|
|
56
|
-
curl http://fukuchi.org/works/qrencode/qrencode-3.1.1.tar.gz | tar xz
|
57
|
-
cd qrencode-3.1.1
|
58
|
-
./configure
|
59
|
-
make
|
60
|
-
sudo make install
|
56
|
+
curl http://fukuchi.org/works/qrencode/qrencode-3.1.1.tar.gz | tar xz
|
57
|
+
cd qrencode-3.1.1
|
58
|
+
./configure
|
59
|
+
make
|
60
|
+
sudo make install
|
61
61
|
|
62
|
-
If
|
62
|
+
If it worked, you should be able to type <tt>qrencode</tt> and get a help
|
63
63
|
message.
|
64
64
|
|
65
65
|
Normally, the build process also expects you to have <tt>libpng</tt>, but
|
@@ -1,8 +1,11 @@
|
|
1
1
|
#include "qrencode.h"
|
2
2
|
#include "ruby.h"
|
3
|
+
#include "errno.h"
|
4
|
+
#include "string.h"
|
3
5
|
|
4
6
|
VALUE mQREncoder;
|
5
7
|
VALUE cQRCode;
|
8
|
+
int errno;
|
6
9
|
|
7
10
|
static void qrcode_free(void *p) {
|
8
11
|
QRcode *qrcode = (QRcode *) p;
|
@@ -235,8 +238,17 @@ static VALUE qr_initialize(VALUE self, VALUE _string, VALUE _version, VALUE _ecl
|
|
235
238
|
int eclevel = FIX2INT(_eclevel);
|
236
239
|
int hint = FIX2INT(_hint);
|
237
240
|
int casesensitive = FIX2INT(_casesensitive);
|
241
|
+
int error = errno;
|
242
|
+
QRcode *code;
|
243
|
+
|
244
|
+
QRinput *input = QRinput_new2(version, eclevel);
|
245
|
+
QRinput_append(input, hint, strlen(string), string);
|
246
|
+
code = QRcode_encodeInput(input);
|
247
|
+
QRinput_free(input);
|
238
248
|
|
239
|
-
|
249
|
+
if (errno != error && errno == 22) {
|
250
|
+
rb_raise(rb_eArgError, "input was too long");
|
251
|
+
}
|
240
252
|
|
241
253
|
if (DATA_PTR(self)) {
|
242
254
|
QRcode_free(DATA_PTR(self));
|
data/lib/qrencoder.rb
CHANGED
@@ -45,7 +45,8 @@ module QREncoder
|
|
45
45
|
correction = corrections[options[:correction] || :low]
|
46
46
|
mode = modes[options[:mode] || :ascii]
|
47
47
|
case_sensitive = options[:case_sensitive] == false ? 0 : 1
|
48
|
-
|
48
|
+
string.upcase! if mode == QR_MODE_AN
|
49
|
+
QRCode.new(string.to_s, version, correction, mode, case_sensitive)
|
49
50
|
end
|
50
51
|
|
51
52
|
def self.corrections
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'chunky_png'
|
2
|
+
|
3
|
+
module QREncoder
|
4
|
+
class PNG
|
5
|
+
attr_reader :canvas,
|
6
|
+
:background,
|
7
|
+
:margin,
|
8
|
+
:pixels_per_module,
|
9
|
+
:points,
|
10
|
+
:width
|
11
|
+
|
12
|
+
##
|
13
|
+
# Takes an optional hash of options. See QRCode#png for details.
|
14
|
+
def initialize(qrcode, options={})
|
15
|
+
@points = qrcode.points
|
16
|
+
@margin = options[:margin] || 4
|
17
|
+
@pixels_per_module= options[:pixels_per_module] || 1
|
18
|
+
@background = options[:transparent] ? ChunkyPNG::Color::TRANSPARENT : ChunkyPNG::Color::WHITE
|
19
|
+
@width = (qrcode.width + (2 * margin)) * pixels_per_module
|
20
|
+
|
21
|
+
@canvas = ChunkyPNG::Image.new(width, width, background)
|
22
|
+
plot_points
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(method, *args, &block)
|
26
|
+
if canvas.respond_to?(method)
|
27
|
+
canvas.send(method, *args, &block)
|
28
|
+
else
|
29
|
+
super
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def respond_to?(method)
|
34
|
+
super || canvas.respond_to?(method)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def plot_points
|
39
|
+
points.each do |point|
|
40
|
+
pixels_per_module.times do |x_offset|
|
41
|
+
x = (point[0] + margin) * pixels_per_module + x_offset
|
42
|
+
pixels_per_module.times do |y_offset|
|
43
|
+
y = (point[1] + margin) * pixels_per_module + y_offset
|
44
|
+
canvas[x,y] = ChunkyPNG::Color::BLACK
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
data/lib/qrencoder/qrcode.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'qrencoder/png'
|
2
2
|
|
3
3
|
module QREncoder
|
4
4
|
# Stores and represents data, points, and/or pixels for a QRCode
|
@@ -22,32 +22,11 @@ module QREncoder
|
|
22
22
|
# [:pixels_per_module] Adjusts the entire PNG image by the given factor, integer. (default: +1+)
|
23
23
|
#
|
24
24
|
def png(options={})
|
25
|
-
|
25
|
+
PNG.new(self, options)
|
26
26
|
end
|
27
27
|
|
28
|
-
##
|
29
|
-
# Returns an instance of PNG::Canvas
|
30
|
-
#
|
31
|
-
# Takes an optional hash of options. See QRCode#png for details.
|
32
28
|
def canvas(options={})
|
33
|
-
|
34
|
-
ppm = options[:pixels_per_module] || 1
|
35
|
-
background = options[:transparent] ? ChunkyPNG::Color::TRANSPARENT : ChunkyPNG::Color::WHITE
|
36
|
-
png_width = (width + (2 * @margin)) * ppm
|
37
|
-
|
38
|
-
canvas = ChunkyPNG::Image.new(png_width, png_width, background)
|
39
|
-
|
40
|
-
points.each do |point|
|
41
|
-
ppm.times do |x_offset|
|
42
|
-
x = (point[0] + @margin) * ppm + x_offset
|
43
|
-
ppm.times do |y_offset|
|
44
|
-
y = (point[1] + @margin) * ppm + y_offset
|
45
|
-
canvas[x,y] = ChunkyPNG::Color::BLACK
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
canvas
|
29
|
+
png(options).canvas
|
51
30
|
end
|
52
31
|
end
|
53
32
|
end
|
data/lib/qrencoder/version.rb
CHANGED
data/spec/integration_spec.rb
CHANGED
@@ -4,8 +4,9 @@ require 'zxing'
|
|
4
4
|
describe QREncoder do
|
5
5
|
context "integration" do
|
6
6
|
let(:path) { File.expand_path("../../tmp/integration.png", __FILE__) }
|
7
|
-
let(:
|
8
|
-
let(:
|
7
|
+
let(:png_options) { Hash.new }
|
8
|
+
let(:encoding_options) { Hash.new }
|
9
|
+
let(:png) { QREncoder.encode(message, encoding_options).png(png_options) }
|
9
10
|
before do
|
10
11
|
File.unlink(path) if File.file?(path)
|
11
12
|
png.save(path)
|
@@ -23,10 +24,26 @@ describe QREncoder do
|
|
23
24
|
it { should == message }
|
24
25
|
end
|
25
26
|
|
27
|
+
context "with alphanumeric characters" do
|
28
|
+
let(:message) { "A63b902f" }
|
29
|
+
let(:encoding_options) do
|
30
|
+
{ :mode => :alphanumeric }
|
31
|
+
end
|
32
|
+
it { should == "A63B902F" }
|
33
|
+
end
|
34
|
+
|
35
|
+
context "with numeric characters" do
|
36
|
+
let(:message) { 83913 }
|
37
|
+
let(:encoding_options) do
|
38
|
+
{ :mode => :numeric }
|
39
|
+
end
|
40
|
+
it { should == "83913" }
|
41
|
+
end
|
42
|
+
|
26
43
|
context "with a custom pixel per module size" do
|
27
44
|
let(:message) { "bigger" }
|
28
|
-
let(:
|
29
|
-
{ :pixels_per_module => 4
|
45
|
+
let(:png_options) do
|
46
|
+
{ :pixels_per_module => 4 }
|
30
47
|
end
|
31
48
|
it { should == message }
|
32
49
|
it "produces a larger png width and height" do
|
@@ -34,4 +51,15 @@ describe QREncoder do
|
|
34
51
|
end
|
35
52
|
end
|
36
53
|
end
|
54
|
+
|
55
|
+
describe "encoding errors" do
|
56
|
+
context "with too-long input" do
|
57
|
+
let(:message) { "a" * 2960 }
|
58
|
+
it "raises an error" do
|
59
|
+
expect {
|
60
|
+
QREncoder.encode(message)
|
61
|
+
}.to raise_error(ArgumentError)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
37
65
|
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe QREncoder::PNG do
|
4
|
+
let(:png) { QREncoder::PNG.new(qrcode, options) }
|
5
|
+
let(:qrcode) { QREncoder.encode("hi") }
|
6
|
+
let(:options) { Hash.new }
|
7
|
+
|
8
|
+
describe "#points" do
|
9
|
+
it "is initialized from QRCode points" do
|
10
|
+
points = []
|
11
|
+
qrcode.stub(:points => points)
|
12
|
+
png.points.should == points
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#width" do
|
17
|
+
before { qrcode.stub(:width => qrcode_width) }
|
18
|
+
let(:qrcode_width) { 21 }
|
19
|
+
subject { png.width }
|
20
|
+
|
21
|
+
context "with a QRCode width of 21, default margin" do
|
22
|
+
it { should == 29 }
|
23
|
+
end
|
24
|
+
|
25
|
+
context "with a QRCode width of 21, margin of 8" do
|
26
|
+
let(:options) { {:margin => 8} }
|
27
|
+
it { should == 37 }
|
28
|
+
end
|
29
|
+
|
30
|
+
context "with QRCode width of 21, pixels-per-module of 2" do
|
31
|
+
let(:qrcode_width) { 21 }
|
32
|
+
let(:options) { {:pixels_per_module => 2} }
|
33
|
+
it { should == 58 }
|
34
|
+
end
|
35
|
+
|
36
|
+
context "with QRCode width of 25, pixels-per-module of 5, margin of 5" do
|
37
|
+
let(:qrcode_width) { 25 }
|
38
|
+
let(:options) { {:pixels_per_module => 5, :margin => 5} }
|
39
|
+
it { should == (10 + 25) * 5 }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#background" do
|
44
|
+
subject { png }
|
45
|
+
|
46
|
+
context "with default options" do
|
47
|
+
it "should be white" do
|
48
|
+
subject.get_pixel(1,1).should == ChunkyPNG::Color::WHITE
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "with transparent set to true" do
|
53
|
+
subject { png.canvas() }
|
54
|
+
let(:options) { {:transparent => true} }
|
55
|
+
it "should be transparent" do
|
56
|
+
subject.get_pixel(1,1).should == ChunkyPNG::Color::TRANSPARENT
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#canvas" do
|
62
|
+
subject { png.canvas }
|
63
|
+
it { should be_kind_of(ChunkyPNG::Image) }
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#save" do
|
67
|
+
it "is delegated to canvas" do
|
68
|
+
path = 'a/path.png'
|
69
|
+
png.canvas.should_receive(:save).with(path)
|
70
|
+
png.save(path)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#to_datastream" do
|
75
|
+
it "is delegated to canvas" do
|
76
|
+
png.canvas.should_receive(:to_datastream)
|
77
|
+
png.to_datastream
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#to_blob" do
|
82
|
+
it "is delegated to canvas" do
|
83
|
+
png.canvas.should_receive(:to_blob)
|
84
|
+
png.to_blob
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "#respond_to?" do
|
89
|
+
context "when method exists" do
|
90
|
+
it "returns true" do
|
91
|
+
png.should respond_to(:width)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "when method does not exist but is defined on ChunkyPNG::Canvas" do
|
96
|
+
it "returns true" do
|
97
|
+
png.should respond_to(:to_datastream)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "when method exists on neither self or canvas" do
|
102
|
+
it "returns false" do
|
103
|
+
png.should_not respond_to(:a_method_that_does_not_exist)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -179,14 +179,14 @@ describe QREncoder::QRCode do
|
|
179
179
|
describe "#png" do
|
180
180
|
let(:qrcode) { QREncoder.encode("hi") }
|
181
181
|
|
182
|
-
it "returns an instance of
|
183
|
-
qrcode.png.should be_kind_of(
|
182
|
+
it "returns an instance of QREncoder::PNG" do
|
183
|
+
qrcode.png.should be_kind_of(QREncoder::PNG)
|
184
184
|
end
|
185
185
|
|
186
186
|
it "sends options to #canvas" do
|
187
|
-
canvas =
|
187
|
+
canvas = QREncoder::PNG.new(qrcode)
|
188
188
|
options = { :margin => 5, :transparent => true }
|
189
|
-
qrcode.should_receive(:
|
189
|
+
qrcode.should_receive(:png).with(options).and_return(canvas)
|
190
190
|
qrcode.png(options)
|
191
191
|
end
|
192
192
|
end
|
@@ -194,7 +194,7 @@ describe QREncoder::QRCode do
|
|
194
194
|
describe "#save_png" do
|
195
195
|
let(:qrcode) { QREncoder.encode("hi") }
|
196
196
|
let(:path) do
|
197
|
-
File.expand_path("
|
197
|
+
File.expand_path("../../../tmp/test.png", __FILE__)
|
198
198
|
end
|
199
199
|
|
200
200
|
before { File.unlink(path) if File.file?(path) }
|
data/spec/qrencoder_spec.rb
CHANGED
@@ -42,7 +42,7 @@ describe QREncoder do
|
|
42
42
|
|
43
43
|
it { should be_a_kind_of(QREncoder::QRCode) }
|
44
44
|
it "encodes using the specified mode" do
|
45
|
-
QREncoder::QRCode.should_receive(:new).with("
|
45
|
+
QREncoder::QRCode.should_receive(:new).with("STRING",
|
46
46
|
1,
|
47
47
|
QREncoder::QR_ECLEVEL_L,
|
48
48
|
QREncoder::QR_MODE_AN,
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: qrencoder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.
|
5
|
+
version: 1.4.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Jacob Harris
|
@@ -12,7 +12,7 @@ autorequire:
|
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
14
|
|
15
|
-
date: 2011-
|
15
|
+
date: 2011-10-02 00:00:00 -05:00
|
16
16
|
default_executable:
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
@@ -23,7 +23,7 @@ dependencies:
|
|
23
23
|
requirements:
|
24
24
|
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 2.4
|
26
|
+
version: "2.4"
|
27
27
|
type: :development
|
28
28
|
version_requirements: *id001
|
29
29
|
- !ruby/object:Gem::Dependency
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
requirements:
|
68
68
|
- - ~>
|
69
69
|
- !ruby/object:Gem::Version
|
70
|
-
version: 1.1
|
70
|
+
version: "1.1"
|
71
71
|
type: :runtime
|
72
72
|
version_requirements: *id005
|
73
73
|
description: |-
|
@@ -84,6 +84,7 @@ extra_rdoc_files:
|
|
84
84
|
- README.rdoc
|
85
85
|
- ext/qrencoder_ext/qrencoder_ext.c
|
86
86
|
files:
|
87
|
+
- lib/qrencoder/png.rb
|
87
88
|
- lib/qrencoder/qrcode.rb
|
88
89
|
- lib/qrencoder/version.rb
|
89
90
|
- lib/qrencoder.rb
|
@@ -92,7 +93,8 @@ files:
|
|
92
93
|
- History.txt
|
93
94
|
- README.rdoc
|
94
95
|
- spec/integration_spec.rb
|
95
|
-
- spec/
|
96
|
+
- spec/qrencoder/png_spec.rb
|
97
|
+
- spec/qrencoder/qrcode_spec.rb
|
96
98
|
- spec/qrencoder_spec.rb
|
97
99
|
- spec/spec_helper.rb
|
98
100
|
has_rdoc: true
|
@@ -125,6 +127,7 @@ specification_version: 3
|
|
125
127
|
summary: Wrapper around the C qrencode library for creating QR Codes
|
126
128
|
test_files:
|
127
129
|
- spec/integration_spec.rb
|
128
|
-
- spec/
|
130
|
+
- spec/qrencoder/png_spec.rb
|
131
|
+
- spec/qrencoder/qrcode_spec.rb
|
129
132
|
- spec/qrencoder_spec.rb
|
130
133
|
- spec/spec_helper.rb
|