qrencoder 1.3.4 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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 codes is readable at
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 code has one of the largest
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 QRCode object directly or use the included
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 if worked, you should be able to type <tt>qrencode</tt> and get a help
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
- QRcode *code = QRcode_encodeString(string, version, eclevel, hint, casesensitive);
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));
@@ -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
- QRCode.new(string, version, correction, mode, case_sensitive)
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
@@ -1,4 +1,4 @@
1
- require 'chunky_png'
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
- canvas(options)
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
- @margin = options[:margin] || 4
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
@@ -1,3 +1,3 @@
1
1
  module QREncoder
2
- VERSION = '1.3.4'
2
+ VERSION = '1.4.0'
3
3
  end
@@ -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(:options) { Hash.new }
8
- let(:png) { QREncoder.encode(message).png(options) }
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(:options) do
29
- { :pixels_per_module => 4, :version => 1 }
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 ChunkyPNG" do
183
- qrcode.png.should be_kind_of(ChunkyPNG::Image)
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 = ChunkyPNG::Canvas.new(1,1)
187
+ canvas = QREncoder::PNG.new(qrcode)
188
188
  options = { :margin => 5, :transparent => true }
189
- qrcode.should_receive(:canvas).with(options).and_return(canvas)
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("../../tmp/test.png", __FILE__)
197
+ File.expand_path("../../../tmp/test.png", __FILE__)
198
198
  end
199
199
 
200
200
  before { File.unlink(path) if File.file?(path) }
@@ -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("string",
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.3.4
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-03-08 00:00:00 -06:00
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.0
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.0
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/qrcode_spec.rb
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/qrcode_spec.rb
130
+ - spec/qrencoder/png_spec.rb
131
+ - spec/qrencoder/qrcode_spec.rb
129
132
  - spec/qrencoder_spec.rb
130
133
  - spec/spec_helper.rb