Added JRuby wrapper for fun scripting times.

git-svn-id: https://zxing.googlecode.com/svn/trunk@1241 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
ecin@copypastel.com 2010-03-05 18:12:55 +00:00
parent 813f4070bf
commit ef3d37cc07
9 changed files with 235 additions and 0 deletions

65
jruby/README.textile Normal file
View file

@ -0,0 +1,65 @@
h2. Decode QR Codes
p. "QR code":http://en.wikipedia.org/wiki/QR_Code generation is well served in the Ruby community, but decoding seems to be stuck in the Java world. This is an attempt to bridge the gap by wrapping the "ZXing":http://code.google.com/p/zxing/ library with JRuby. ZXing conveniently decodes a plethora of barcodes. Their site has a complete list.
h2. Requirements
* JRuby (tested with 1.4.0)
* shoulda (for testing)
h2. Using the ZXing module/singleton.
<pre>
<code>
require 'zxing'
# You can decode a URL...
ZXing.decode 'http://2d-code.co.uk/images/bbc-logo-in-qr-code.gif'
# ... or a file path...
ZXing.decode '/Users/ecin/qrcode.png'
# ... or a File object...
ZXing.decode File.open('qrcode.png')
# ... or anything that returns a URL or file path when #path or #to_s
# is called on it.
class Image
attr_reader :path
def initialize(path); @path = path end
end
image = Image.new('qrcode.png')
ZXing.decode image
# #decode returns nil if it can't decode the image.
ZXing.decode 'image_without_a_code.png'
# => nil
# #decode! will raise an error if it can't decode the image.
ZXing.decode! 'image_without_a_code.png'
# => NativeException
# Feel free to include ZXing to shorten the call.
include ZXing
decode 'qrcode.png'
</code>
</pre>
h2. Including the Decodable module.
p. A Decodable module is included (pun intended) to ease using the library with objects that return the URL or file path to decode when #path or #to_s is called.
<pre>
<code>
require 'zxing/decodable'
class File
include Decodable
end
file = File.open('qrcode.png')
file.decode
</code>
</pre>

BIN
jruby/lib/core.jar Normal file

Binary file not shown.

BIN
jruby/lib/javase.jar Normal file

Binary file not shown.

56
jruby/lib/zxing.rb Normal file
View file

@ -0,0 +1,56 @@
raise "ZXing requires JRuby" unless defined?(JRuby)
require File.expand_path( File.dirname(__FILE__) + '/core.jar' ) # ZXing core classes
require File.expand_path( File.dirname(__FILE__) + '/javase.jar' ) # ZXing JavaSE classes
require 'uri'
# Google ZXing classes
java_import com.google.zxing.MultiFormatReader
java_import com.google.zxing.BinaryBitmap
java_import com.google.zxing.Binarizer
java_import com.google.zxing.common.GlobalHistogramBinarizer
java_import com.google.zxing.LuminanceSource
java_import com.google.zxing.client.j2se.BufferedImageLuminanceSource
# Standard Java classes
java_import javax.imageio.ImageIO
java_import java.net.URL
module ZXing
@@decoder = MultiFormatReader.new
# Transform the module into a singleton!
extend self
def decode(descriptor)
begin
decode!(descriptor)
rescue NativeException
return nil
end
end
def decode!(descriptor)
descriptor = descriptor.path if descriptor.respond_to? :path
descriptor = descriptor.to_s
descriptor = case descriptor
when URI.regexp(['http', 'https'])
URL.new(descriptor)
else
Java::JavaIO::File.new(descriptor)
end
image = ImageIO.read(descriptor)
bitmap = to_bitmap(image)
@@decoder.decode(bitmap).to_s
end
private
def to_bitmap(image)
luminance = BufferedImageLuminanceSource.new(image)
binarizer = GlobalHistogramBinarizer.new(luminance)
BinaryBitmap.new(binarizer)
end
end

View file

@ -0,0 +1,11 @@
require File.expand_path( File.dirname(__FILE__) + '/../zxing')
module Decodable
def decode
ZXing.decode(self)
end
def decode!
ZXing.decode!(self)
end
end

BIN
jruby/test/qrcode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

View file

@ -0,0 +1,4 @@
$LOAD_PATH.unshift File.expand_path( File.dirname(__FILE__) + '/../lib')
$LOAD_PATH.unshift File.expand_path( File.dirname(__FILE__) )
require 'shoulda'

View file

@ -0,0 +1,40 @@
#!/usr/bin/env jruby --headless -rubygems
require File.expand_path( File.dirname(__FILE__) + '/../test_helper')
require 'zxing/decodable'
class DecodableTest < Test::Unit::TestCase
class Object::File
include Decodable
end
class URL
include Decodable
def initialize(path)
@path = path
end
def path; @path end
end
context "A Decodable module" do
setup do
@file = File.open( File.expand_path( File.dirname(__FILE__) + '/../qrcode.png' ))
@uri = URL.new "http://2d-code.co.uk/images/bbc-logo-in-qr-code.gif"
@bad_uri = URL.new "http://google.com"
end
should "provide #decode to decode the return value of #path" do
assert_equal @file.decode, ZXing.decode(@file.path)
assert_equal @uri.decode, ZXing.decode(@uri.path)
assert_nil @bad_uri.decode
end
should "provide #decode! as well" do
assert_equal @file.decode!, ZXing.decode(@file.path)
assert_equal @uri.decode!, ZXing.decode(@uri.path)
assert_raise(NativeException) { @bad_uri.decode! }
end
end
end

59
jruby/test/zxing_test.rb Executable file
View file

@ -0,0 +1,59 @@
#!/usr/bin/env jruby --headless -rubygems
require File.expand_path( File.dirname(__FILE__) + '/test_helper')
require 'zxing'
class ZXingTest < Test::Unit::TestCase
context "A QR decoder singleton" do
class Foo < Struct.new(:v); def to_s; self.v; end; end
setup do
@decoder = ZXing
@uri = "http://2d-code.co.uk/images/bbc-logo-in-qr-code.gif"
@path = File.expand_path( File.dirname(__FILE__) + '/qrcode.png')
@file = File.new(@path)
@google_logo = "http://www.google.com/logos/grandparentsday10.gif"
@uri_result = "http://bbc.co.uk/programmes"
@path_result = "http://rubyflow.com"
end
should "decode a URL" do
assert_equal @decoder.decode(@uri), @uri_result
end
should "decode a file path" do
assert_equal @decoder.decode(@path), @path_result
end
should "return nil if #decode fails" do
assert_nil @decoder.decode(@google_logo)
end
should "raise an exception if #decode! fails" do
assert_raise(NativeException) { @decoder.decode!(@google_logo) }
end
should "decode objects that respond to #path" do
assert_equal @decoder.decode(@file), @path_result
end
should "call #to_s to argument passed in as a last resort" do
assert_equal @decoder.decode(Foo.new(@path)), @path_result
end
end
context "A QR decoder module" do
setup do
class SpyRing; include ZXing end
@ring = SpyRing.new
end
should "include #decode and #decode! into classes" do
assert_equal defined?(@ring.decode), "method"
assert_equal defined?(@ring.decode!), "method"
end
end
end