qrtools 1.0.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.
Files changed (66) hide show
  1. data/History.txt +6 -0
  2. data/Manifest.txt +65 -0
  3. data/README.txt +75 -0
  4. data/Rakefile +49 -0
  5. data/bin/qrdecode +14 -0
  6. data/ext/qrtools/Makefile.in +65 -0
  7. data/ext/qrtools/bitstream.cpp +147 -0
  8. data/ext/qrtools/bitstream.h +48 -0
  9. data/ext/qrtools/codedata.cpp +506 -0
  10. data/ext/qrtools/codedata.h +95 -0
  11. data/ext/qrtools/container.cpp +288 -0
  12. data/ext/qrtools/container.h +175 -0
  13. data/ext/qrtools/decodeqr.h +286 -0
  14. data/ext/qrtools/ecidecoder.cpp +341 -0
  15. data/ext/qrtools/ecidecoder.h +110 -0
  16. data/ext/qrtools/extconf.rb +24 -0
  17. data/ext/qrtools/formatinfo.cpp +195 -0
  18. data/ext/qrtools/formatinfo.h +113 -0
  19. data/ext/qrtools/galois.cpp +593 -0
  20. data/ext/qrtools/galois.h +134 -0
  21. data/ext/qrtools/imagereader.cpp +1099 -0
  22. data/ext/qrtools/imagereader.h +127 -0
  23. data/ext/qrtools/libdecodeqr.cpp +195 -0
  24. data/ext/qrtools/libdecodeqr.dep +80 -0
  25. data/ext/qrtools/libdecodeqr.dsp +160 -0
  26. data/ext/qrtools/libdecodeqr.dsw +29 -0
  27. data/ext/qrtools/libdecodeqr.mak +245 -0
  28. data/ext/qrtools/qrerror.h +40 -0
  29. data/ext/qrtools/qrtools.c +17 -0
  30. data/ext/qrtools/qrtools.h +21 -0
  31. data/ext/qrtools/qrtools_decoder.c +123 -0
  32. data/ext/qrtools/qrtools_decoder.h +10 -0
  33. data/ext/qrtools/qrtools_encoder.c +63 -0
  34. data/ext/qrtools/qrtools_encoder.h +10 -0
  35. data/ext/qrtools/qrtools_header.c +51 -0
  36. data/ext/qrtools/qrtools_header.h +10 -0
  37. data/ext/qrtools/qrtools_image.c +80 -0
  38. data/ext/qrtools/qrtools_image.h +11 -0
  39. data/ext/qrtools/qrtools_qrcode.c +36 -0
  40. data/ext/qrtools/qrtools_qrcode.h +10 -0
  41. data/ext/qrtools/qrtools_ui_camera.c +58 -0
  42. data/ext/qrtools/qrtools_ui_camera.h +10 -0
  43. data/ext/qrtools/qrtools_ui_window.c +40 -0
  44. data/ext/qrtools/qrtools_ui_window.h +10 -0
  45. data/ext/qrtools/qrtypes.h +42 -0
  46. data/ext/qrtools/version.h +42 -0
  47. data/lib/qrtools.rb +11 -0
  48. data/lib/qrtools/decoder.rb +17 -0
  49. data/lib/qrtools/encoder.rb +14 -0
  50. data/lib/qrtools/image.rb +43 -0
  51. data/lib/qrtools/qrcode.rb +54 -0
  52. data/lib/qrtools/ui/camera.rb +28 -0
  53. data/lib/qrtools/ui/window.rb +16 -0
  54. data/lib/qrtools/version.rb +3 -0
  55. data/qrtools.gemspec +38 -0
  56. data/test/assets/01-1.jpg +0 -0
  57. data/test/helper.rb +17 -0
  58. data/test/test_decoder.rb +67 -0
  59. data/test/test_encoder.rb +35 -0
  60. data/test/test_header.rb +14 -0
  61. data/test/test_image.rb +19 -0
  62. data/test/test_qrcode.rb +78 -0
  63. data/test/test_qrdecode.rb +0 -0
  64. data/test/ui/test_camera.rb +43 -0
  65. data/test/ui/test_window.rb +34 -0
  66. metadata +138 -0
@@ -0,0 +1,42 @@
1
+ /////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // version.h --a part of libdecodeqr
4
+ //
5
+ // Copyright(C) 2007 NISHI Takao <zophos@koka-in.org>
6
+ // JMA (Japan Medical Association)
7
+ // NaCl (Network Applied Communication Laboratory Ltd.)
8
+ //
9
+ // This is free software with ABSOLUTELY NO WARRANTY.
10
+ // You can redistribute and/or modify it under the terms of LGPL.
11
+ //
12
+ // $Id$
13
+ //
14
+ #ifndef __QR_LIBDECODEQR_VERSION__
15
+ #define __QR_LIBDECODEQR_VERSION__
16
+
17
+ #define LIBDECODEQR_PRODUCTNAME "libdecodeqr"
18
+ #define LIBDECODEQR_VERSION_MAJOR 0
19
+ #define LIBDECODEQR_VERSION_MINOR 9
20
+ #define LIBDECODEQR_VERSION_TEENY 4
21
+ #define LIBDECODEQR_VERSION_SUFFIX "-dev"
22
+ #define LIBDECODEQR_VERSION_REVISION "$Rev: 45 $"
23
+
24
+ //
25
+ // a voodoo magic
26
+ //
27
+ #define LIBDECODEQR_VERSION_CAT(a,b,c,d,e) LIBDECODEQR_VERSION_CATX(a,b,c,d,e)
28
+ #define LIBDECODEQR_VERSION_CATX(a,b,c,d,e) #a "." #b "." #c d " (" e ")"
29
+
30
+ #define LIBDECODEQR_VERSION LIBDECODEQR_VERSION_CAT(\
31
+ LIBDECODEQR_VERSION_MAJOR,\
32
+ LIBDECODEQR_VERSION_MINOR,\
33
+ LIBDECODEQR_VERSION_TEENY,\
34
+ LIBDECODEQR_VERSION_SUFFIX,\
35
+ LIBDECODEQR_VERSION_REVISION)
36
+
37
+ #define LIBDECODEQR_VERSION_DESCRIPTION \
38
+ LIBDECODEQR_PRODUCTNAME " " LIBDECODEQR_VERSION
39
+
40
+ static const char *libdecodeqr_version_description=
41
+ LIBDECODEQR_VERSION_DESCRIPTION;
42
+ #endif
@@ -0,0 +1,11 @@
1
+ require 'qrtools/qrtools' # native
2
+ require 'qrtools/decoder'
3
+ require 'qrtools/encoder'
4
+ require 'qrtools/qrcode'
5
+ require 'qrtools/image'
6
+ require 'qrtools/ui/camera'
7
+ require 'qrtools/ui/window'
8
+
9
+ module QRTools
10
+ VERSION = '1.0.0'
11
+ end
@@ -0,0 +1,17 @@
1
+ module QRTools
2
+ class Decoder
3
+ class << self
4
+ def decode image, size = 25, delta = 10
5
+ decoder = new(image)
6
+ 25.step(3, -2) { |i|
7
+ return decoder if decoder.decode(size, delta)
8
+ }
9
+ decoder
10
+ end
11
+ end
12
+
13
+ def decode size = 25, delta = 10
14
+ native_decode(size, delta)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ module QRTools
2
+ class Encoder
3
+ NULL = -1 # Terminator (NUL character)
4
+ NUMERIC = 0 # Numeric mode
5
+ ALPHA_NUM = 1 # Alphabet-numeric mode
6
+ EIGHT_BIT = 2 # 8-bit data mode
7
+ KANJI = 3 # Kanji (shift-jis) mode
8
+
9
+ L = 0 # Error Correction L (Lowest)
10
+ M = 1 # Error Correction M
11
+ Q = 2 # Error Corretion Q
12
+ H = 3 # Error Corretion H (highest)
13
+ end
14
+ end
@@ -0,0 +1,43 @@
1
+ require 'tempfile'
2
+
3
+ module QRTools
4
+ class Image
5
+ Point = Struct.new(:x, :y)
6
+
7
+ ###
8
+ # Draw a line on this image:
9
+ #
10
+ # draw_line :from => 0, :to => 100, :thickness => 5
11
+ def draw_line options
12
+ raise ArgumentError unless options.key?(:from)
13
+ raise ArgumentError unless options.key?(:to)
14
+ options = {
15
+ :r => 255,
16
+ :g => 0,
17
+ :b => 0,
18
+ :thickness => 1,
19
+ :type => 8,
20
+ :shift => 0,
21
+ }.merge(options)
22
+ native_draw_line(
23
+ options[:from],
24
+ options[:to],
25
+ options[:r],
26
+ options[:g],
27
+ options[:b],
28
+ options[:thickness],
29
+ options[:type],
30
+ options[:shift]
31
+ )
32
+ end
33
+
34
+ ###
35
+ # Convert this Image to an OSX::NSImage
36
+ def to_nsimage
37
+ require 'osx/cocoa'
38
+ filename = File.join(Dir::tmpdir, 'out.jpg')
39
+ save(filename)
40
+ OSX::NSImage.alloc.initWithContentsOfFile filename
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,54 @@
1
+ require 'enumerator'
2
+ require 'png'
3
+
4
+ module QRTools
5
+ class QRCode
6
+ class << self
7
+ def decode *args, &block
8
+ Decoder.decode *args, &block
9
+ end
10
+
11
+ def encode *args, &block
12
+ Encoder.encode *args, &block
13
+ end
14
+ end
15
+
16
+ def to_matrix
17
+ codes = []
18
+ data.unpack("C#{width ** 2}").each_slice(width) { |row|
19
+ codes << row.map { |x| x & 0x1 == 1 }
20
+ }
21
+ codes
22
+ end
23
+
24
+ def to_s
25
+ to_matrix.map { |row|
26
+ row.map { |bit| bit ? '#' : ' ' }.join
27
+ }.join("\n")
28
+ end
29
+
30
+ def to_png scale = 4, border = 10
31
+ # Add 2 extra rows / columns for white borders
32
+ size = (width + border) * scale
33
+ canvas = PNG::Canvas.new(size, size, PNG::Color::White)
34
+
35
+ scaled_matrix = []
36
+ to_matrix.each do |row|
37
+ scaled_row = row.map { |bit|
38
+ [bit] * scale
39
+ }.flatten
40
+ scaled_matrix += ([scaled_row] * scale)
41
+ end
42
+
43
+ factor = border / 2 * scale
44
+ scaled_matrix.each_with_index { |row, i|
45
+ x = i + factor
46
+ row.each_with_index { |bit, j|
47
+ y = j + factor
48
+ canvas[x, y] = bit ? PNG::Color::Black : PNG::Color::White
49
+ }
50
+ }
51
+ PNG.new(canvas).to_blob
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,28 @@
1
+ require 'thread'
2
+
3
+ module QRTools
4
+ module UI
5
+ class Camera
6
+ @@locks = Hash.new { |h,k| h[k] = Mutex.new }
7
+
8
+ def initialize camera_number
9
+ @camera_number = camera_number
10
+ if block_given?
11
+ start
12
+ yield self
13
+ stop
14
+ end
15
+ end
16
+
17
+ def start
18
+ @@locks[@camera_number].lock
19
+ native_start
20
+ end
21
+
22
+ def stop
23
+ @@locks[@camera_number].unlock
24
+ native_stop
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,16 @@
1
+ module QRTools
2
+ module UI
3
+ class Window
4
+ ###
5
+ # Create a new window with +name+
6
+ def initialize name
7
+ @name = name
8
+ if block_given?
9
+ show
10
+ yield self
11
+ hide
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module QRTools
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,38 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{qrtools}
5
+ s.version = "1.0.0.20090212084338"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Aaron Patterson"]
9
+ s.date = %q{2009-02-12}
10
+ s.default_executable = %q{qrdecode}
11
+ s.description = %q{FIX (describe your package)}
12
+ s.email = ["aaronp@rubyforge.org"]
13
+ s.executables = ["qrdecode"]
14
+ s.extensions = ["ext/qrtools/extconf.rb"]
15
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
16
+ s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "bin/qrdecode", "ext/qrtools/Makefile.in", "ext/qrtools/bitstream.cpp", "ext/qrtools/bitstream.h", "ext/qrtools/codedata.cpp", "ext/qrtools/codedata.h", "ext/qrtools/container.cpp", "ext/qrtools/container.h", "ext/qrtools/decodeqr.h", "ext/qrtools/ecidecoder.cpp", "ext/qrtools/ecidecoder.h", "ext/qrtools/extconf.rb", "ext/qrtools/formatinfo.cpp", "ext/qrtools/formatinfo.h", "ext/qrtools/galois.cpp", "ext/qrtools/galois.h", "ext/qrtools/imagereader.cpp", "ext/qrtools/imagereader.h", "ext/qrtools/libdecodeqr.cpp", "ext/qrtools/libdecodeqr.dep", "ext/qrtools/libdecodeqr.dsp", "ext/qrtools/libdecodeqr.dsw", "ext/qrtools/libdecodeqr.mak", "ext/qrtools/qrerror.h", "ext/qrtools/qrtools.c", "ext/qrtools/qrtools.h", "ext/qrtools/qrtools_decoder.c", "ext/qrtools/qrtools_decoder.h", "ext/qrtools/qrtools_header.c", "ext/qrtools/qrtools_header.h", "ext/qrtools/qrtools_image.c", "ext/qrtools/qrtools_image.h", "ext/qrtools/qrtypes.h", "ext/qrtools/version.h", "lib/qrtools.rb", "test/assets/01-1.jpg", "test/helper.rb", "test/test_decoder.rb", "test/test_header.rb", "test/test_image.rb", "test/test_qrdecode.rb"]
17
+ s.has_rdoc = true
18
+ s.homepage = %q{FIX (url)}
19
+ s.rdoc_options = ["--main", "README.txt"]
20
+ s.require_paths = ["lib", "ext"]
21
+ s.rubyforge_project = %q{qrtools}
22
+ s.rubygems_version = %q{1.3.1}
23
+ s.summary = %q{FIX (describe your package)}
24
+ s.test_files = ["test/test_decoder.rb", "test/test_header.rb", "test/test_image.rb", "test/test_qrdecode.rb"]
25
+
26
+ if s.respond_to? :specification_version then
27
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
28
+ s.specification_version = 2
29
+
30
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
31
+ s.add_development_dependency(%q<hoe>, [">= 1.8.2"])
32
+ else
33
+ s.add_dependency(%q<hoe>, [">= 1.8.2"])
34
+ end
35
+ else
36
+ s.add_dependency(%q<hoe>, [">= 1.8.2"])
37
+ end
38
+ end
Binary file
@@ -0,0 +1,17 @@
1
+ require 'test/unit'
2
+ require 'tempfile'
3
+
4
+ %w(../lib ../ext).each do |path|
5
+ $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), path)))
6
+ end
7
+
8
+ require 'rubygems'
9
+ require 'qrtools'
10
+
11
+ class QRToolsTestCase < Test::Unit::TestCase
12
+ ASSETS = File.expand_path(File.join(File.dirname(__FILE__), 'assets'))
13
+
14
+ unless RUBY_VERSION >= '1.9'
15
+ undef :default_test
16
+ end
17
+ end
@@ -0,0 +1,67 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "helper"))
2
+
3
+ class DecoderTestCase < QRToolsTestCase
4
+ def test_new
5
+ img = QRTools::Image.load(File.join(ASSETS, '01-1.jpg'))
6
+ assert decoder = QRTools::Decoder.new(img)
7
+ assert decoder.decode
8
+ end
9
+
10
+ def test_coderegion_vertexes
11
+ img = QRTools::Image.load(File.join(ASSETS, '01-1.jpg'))
12
+ assert decoder = QRTools::QRCode.decode(img)
13
+ verts = decoder.coderegion_vertexes
14
+ assert_equal 4, verts.length
15
+ end
16
+
17
+ def test_draw_vertexes
18
+ img = QRTools::Image.load(File.join(ASSETS, '01-1.jpg'))
19
+ assert decoder = QRTools::Decoder.decode(img)
20
+ verts = decoder.coderegion_vertexes
21
+ from = verts.last
22
+ verts.each do |to|
23
+ img.draw_line :from => from, :to => to, :thickness => 5
24
+ from = to
25
+ end
26
+ end
27
+
28
+ def test_cannot_decode
29
+ QRTools::UI::Camera.new(0) do |camera|
30
+ assert ! QRTools::Decoder.new(camera.capture).decode
31
+ end
32
+ end
33
+
34
+ def test_binarized_image
35
+ img = QRTools::Image.load(File.join(ASSETS, '01-1.jpg'))
36
+ decoder = QRTools::Decoder.new(img)
37
+ decoder.decode
38
+ QRTools::UI::Window.new("foo") do |window|
39
+ window.display decoder.binarized_image
40
+ end
41
+ end
42
+
43
+ def test_set_image
44
+ img = QRTools::Image.load(File.join(ASSETS, '01-1.jpg'))
45
+ assert decoder = QRTools::Decoder.new(img)
46
+ decoder.image = img
47
+ end
48
+
49
+ def test_decode
50
+ img = QRTools::Image.load(File.join(ASSETS, '01-1.jpg'))
51
+ assert decoder = QRTools::Decoder.decode(img)
52
+ end
53
+
54
+ def test_header
55
+ img = QRTools::Image.load(File.join(ASSETS, '01-1.jpg'))
56
+ assert decoder = QRTools::Decoder.decode(img)
57
+ assert decoder.header
58
+ end
59
+
60
+ def test_body
61
+ img = QRTools::Image.load(File.join(ASSETS, '01-1.jpg'))
62
+ assert decoder = QRTools::Decoder.decode(img)
63
+ assert decoder.body
64
+ assert_match 'amazon', decoder.body
65
+ end
66
+ end
67
+
@@ -0,0 +1,35 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "helper"))
2
+
3
+ class EncoderTestCase < QRToolsTestCase
4
+ def test_encode
5
+ assert code = QRTools::Encoder.encode('hello world')
6
+ end
7
+
8
+ def test_encode_with_mode
9
+ assert code = QRTools::QRCode.encode('元気',
10
+ :mode => QRTools::Encoder::KANJI
11
+ )
12
+ end
13
+
14
+ def test_encode_with_version
15
+ assert code = QRTools::Encoder.encode('hello world',
16
+ :version => 1
17
+ )
18
+ end
19
+
20
+ def test_encode_with_case_sensitivity_off
21
+ assert code = QRTools::Encoder.encode('hello world',
22
+ :case_sensitive => false
23
+ )
24
+ end
25
+
26
+ def test_encode_with_error_correction
27
+ assert code = QRTools::Encoder.encode('hello world',
28
+ :error_correction => QRTools::Encoder::L
29
+ )
30
+ end
31
+
32
+ def test_code_has_a_width
33
+ assert code = QRTools::Encoder.encode('hello world')
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "helper"))
2
+
3
+ class HeaderTestCase < QRToolsTestCase
4
+ def setup
5
+ img = QRTools::Image.load(File.join(ASSETS, '01-1.jpg'))
6
+ decoder = QRTools::Decoder.decode(img)
7
+ @header = decoder.header
8
+ end
9
+ %w{ model version level character_size byte_size }.each do |m|
10
+ define_method(:"test_#{m}") do
11
+ assert @header.send(:"#{m}")
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "helper"))
2
+
3
+ class ImageTestCase < QRToolsTestCase
4
+ def test_load
5
+ assert img = QRTools::Image.load(File.join(ASSETS, '01-1.jpg'))
6
+ end
7
+
8
+ def test_save
9
+ filename = File.join(Dir::tmpdir, 'out.jpg')
10
+ img = QRTools::Image.load(File.join(ASSETS, '01-1.jpg'))
11
+ assert img.save(filename)
12
+ assert File.exist?(filename)
13
+ end
14
+
15
+ def test_to_nsimage
16
+ img = QRTools::Image.load(File.join(ASSETS, '01-1.jpg'))
17
+ assert img.to_nsimage
18
+ end
19
+ end
@@ -0,0 +1,78 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "helper"))
2
+
3
+ class QRCodeTestCase < QRToolsTestCase
4
+ def setup
5
+ @code = QRTools::Encoder.encode('http://tenderlovemaking.com/')
6
+ end
7
+
8
+ def test_new
9
+ encoder = QRTools::Encoder.new
10
+ end
11
+
12
+ def test_version
13
+ encoder = QRTools::Encoder.new
14
+ assert encoder.version
15
+ end
16
+
17
+ def test_version=
18
+ encoder = QRTools::Encoder.new
19
+ encoder.version = 1
20
+ assert_equal 1, encoder.version
21
+ end
22
+
23
+ def test_code_has_a_width
24
+ assert @code.width
25
+ end
26
+
27
+ def test_code_has_a_version
28
+ assert @code.version
29
+ end
30
+
31
+ def test_code_has_data
32
+ assert @code.data
33
+ end
34
+
35
+ def test_to_matrix
36
+ assert @code.to_matrix
37
+ end
38
+
39
+ def test_to_s
40
+ assert @code.to_s
41
+ end
42
+
43
+ def test_roundtrip
44
+ filename = File.join(Dir::tmpdir, 'out.png')
45
+ File.open(filename, 'wb') { |f|
46
+ f.write @code.to_png
47
+ }
48
+ img = QRTools::Image.load(filename)
49
+ assert decoder = QRTools::Decoder.decode(img)
50
+ assert_equal 'http://tenderlovemaking.com/', decoder.body.downcase
51
+ end
52
+
53
+ class Foo < Struct.new(:foo)
54
+ end
55
+
56
+ def test_marshal_roundtrip
57
+ object = Foo.new("foo")
58
+ packed = [Marshal.dump(object)].pack('m')
59
+
60
+ # Encode packed object
61
+ assert code = QRTools::Encoder.encode(packed,
62
+ :case_sensitive => true,
63
+ :error_correction => QRTools::Encoder::H
64
+ )
65
+
66
+ filename = File.join('/tmp', 'out.png')
67
+ File.open(filename, 'wb') { |f| f.write code.to_png }
68
+
69
+ img = QRTools::Image.load(filename)
70
+ assert decoder = QRTools::Decoder.decode(img)
71
+
72
+ # Make sure we can read the packed object
73
+ assert_equal packed, decoder.body
74
+
75
+ foo = Marshal.load(decoder.body.unpack('m').first)
76
+ assert_equal object.foo, foo.foo
77
+ end
78
+ end