forked from willglynn/ruby-zbar
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
375 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
require 'ffi' | ||
|
||
require 'zbar/lib' | ||
require 'zbar/symbol' | ||
require 'zbar/processor' | ||
require 'zbar/image' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
module ZBar | ||
|
||
# Encapsulates a ZBar Image data structure. | ||
class Image | ||
# Instantiates a new Image object, either by creating an empty one, | ||
# or wrapping the supplied pointer. | ||
def initialize(pointer=nil) | ||
@img = FFI::AutoPointer.new( | ||
pointer || ZBar.zbar_image_create, | ||
ZBar.method(:zbar_image_destroy) | ||
) | ||
end | ||
|
||
# Instantiates an Image given JPEG data. | ||
# | ||
# This function uses the internal ZBar conversion function to decode the JPEG | ||
# and convert it into a greyscale image suitable for further processing. | ||
# This conversion may fail if ZBar was not built with <tt>--with-jpeg</tt>. | ||
def self.from_jpeg(io_or_string) | ||
if io_or_string.respond_to?(:read) | ||
io_or_string = io_or_string.read | ||
end | ||
|
||
jpeg_image = new() | ||
jpeg_image.set_data(ZBar::Format::JPEG, io_or_string) | ||
return jpeg_image.convert(ZBar::Format::Y800) | ||
end | ||
|
||
# Instantiates an Image given raw PGM data. | ||
# | ||
# PGM is a NetPBM format, encoding width, height, and greyscale data, one byte | ||
# per pixel. It is therefore ideally suited for loading into ZBar, which | ||
# operates natively on Y800 pixel data--identical to the data section of a PGM | ||
# file. | ||
# | ||
# The data is described in greater detail at | ||
# http://netpbm.sourceforge.net/doc/pgm.html. | ||
def self.from_pgm(io_or_string) | ||
if io_or_string.respond_to?(:read) | ||
io_or_string = io_or_string.read | ||
end | ||
|
||
image_data = io_or_string.gsub(/^(P5)\s([0-9]+)\s([0-9]+)\s([0-9]+)\s/, '') | ||
if $1 != 'P5' | ||
raise ArgumentError, "input must be a PGM file" | ||
end | ||
|
||
width, height, max_val = $2.to_i, $3.to_i, $4.to_i | ||
|
||
if max_val != 255 | ||
raise ArgumentError, "maximum value must be 255" | ||
end | ||
|
||
image = new() | ||
image.set_data(ZBar::Format::Y800, image_data, width, height) | ||
image | ||
end | ||
|
||
# Load arbitrary data from a string into the Image object. | ||
# | ||
# Format must be a ZBar::Format constant. See the ZBar documentation | ||
# for what formats are supported, and how the data should be formatted. | ||
# | ||
# Most everyone should use one of the <tt>Image.from_*</tt> methods instead. | ||
def set_data(format, data, width=nil, height=nil) | ||
ZBar.zbar_image_set_format(@img, format) | ||
|
||
# Note the @buffer jog: it's to keep Ruby GC from losing the last | ||
# reference to the old @buffer before calling image_set_data. | ||
new_buffer = FFI::MemoryPointer.from_string(data) | ||
ZBar.zbar_image_set_data(@img, new_buffer, data.size, nil) | ||
@buffer = new_buffer | ||
|
||
if width && height | ||
ZBar.zbar_image_set_size(@img, width.to_i, height.to_i) | ||
end | ||
end | ||
|
||
# Ask ZBar to convert this image to a new format, returning a new Image. | ||
# | ||
# Not all conversions are possible: for example, if ZBar was built without | ||
# JPEG support, it cannot convert JPEGs into anything else. | ||
def convert(format) | ||
ptr = ZBar.zbar_image_convert(@img, format) | ||
if ptr.null? | ||
raise ArgumentError, "conversion failed" | ||
else | ||
Image.new(ptr) | ||
end | ||
end | ||
|
||
# Attempt to recognize barcodes in this image, using the supplied processor | ||
# (if any), falling back to defaults. | ||
# | ||
# Returns an array of ZBar::Symbol objects. | ||
def process(processor = nil) | ||
processor ||= Processor.new | ||
processor.process(self) | ||
end | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
module ZBar | ||
extend FFI::Library | ||
ffi_lib 'zbar' | ||
|
||
attach_function :zbar_symbol_get_type, [:pointer], :int | ||
attach_function :zbar_symbol_get_data, [:pointer], :string | ||
attach_function :zbar_symbol_get_type, [:pointer], :int | ||
attach_function :zbar_symbol_get_quality, [:pointer], :int | ||
attach_function :zbar_symbol_get_loc_size, [:pointer], :uint | ||
attach_function :zbar_symbol_get_loc_x, [:pointer, :uint], :int | ||
attach_function :zbar_symbol_get_loc_y, [:pointer, :uint], :int | ||
attach_function :zbar_symbol_next, [:pointer], :pointer | ||
|
||
attach_function :zbar_image_create, [], :pointer | ||
attach_function :zbar_image_destroy, [:pointer], :void | ||
attach_function :zbar_image_first_symbol, [:pointer], :pointer | ||
attach_function :zbar_image_set_format, [:pointer, :ulong], :void | ||
attach_function :zbar_image_convert, [:pointer, :ulong], :pointer | ||
attach_function :zbar_image_set_size, [:pointer, :uint, :uint], :void | ||
attach_function :zbar_image_set_data, [:pointer, :buffer_in, :uint, :pointer], :void | ||
|
||
attach_function :zbar_processor_create, [:int], :pointer | ||
attach_function :zbar_processor_destroy, [:pointer], :void | ||
attach_function :zbar_processor_init, [:pointer, :string, :int], :int | ||
|
||
attach_function :zbar_process_image, [:pointer, :pointer], :int | ||
|
||
attach_function :zbar_set_verbosity, [:int], :void | ||
attach_function :zbar_get_symbol_name, [:int], :string | ||
attach_function :zbar_get_addon_name, [:int], :string | ||
attach_function :_zbar_error_spew, [:pointer, :int], :int | ||
|
||
module Format #:nodoc: | ||
%w(JPEG Y800 GREY).each { |format| | ||
const_set(format.to_sym, format.unpack('V')[0]) | ||
} | ||
end | ||
|
||
# Sets the verbosity of the underlying ZBar library, which writes | ||
# directly to stderr. | ||
def self.verbosity=(v) | ||
zbar_set_verbosity(v.to_i) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
module ZBar | ||
class Processor | ||
# Create a new processor. | ||
def initialize(threads = 0) | ||
@processor = FFI::AutoPointer.new( | ||
ZBar.zbar_processor_create(threads), | ||
ZBar.method(:zbar_processor_destroy) | ||
) | ||
|
||
if ZBar.zbar_processor_init(@processor, nil, 0) > 0 | ||
ZBar._zbar_error_spew(@processor, 0) | ||
raise "error!" | ||
end | ||
end | ||
|
||
# Attempt to recognize barcodes in this image. Raises an exception if ZBar | ||
# signals an error, otherwise returns an array of ZBar::Symbol objects. | ||
def process(image) | ||
raise ArgumentError, "process() operates only on ZBar::Image objects" unless image.kind_of?(ZBar::Image) | ||
image = image.instance_variable_get(:@img) | ||
|
||
if ZBar.zbar_process_image(@processor, image) != 0 | ||
raise ArgumentError, "processing failed" | ||
end | ||
|
||
out = [] | ||
|
||
sym = ZBar.zbar_image_first_symbol(image) | ||
until sym.null? | ||
out << Symbol.new(sym) | ||
sym = ZBar.zbar_symbol_next(sym) | ||
end | ||
|
||
out | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
module ZBar | ||
|
||
class Symbol | ||
attr_reader :symbology, :data, :addon, :quality, :location | ||
|
||
def initialize(symbol=nil) | ||
if symbol | ||
type = ZBar.zbar_symbol_get_type(symbol) | ||
@symbology = ZBar.zbar_get_symbol_name(type) | ||
@data = ZBar.zbar_symbol_get_data(symbol) | ||
@addon = ZBar.zbar_get_addon_name(type) | ||
@quality = ZBar.zbar_symbol_get_quality(symbol) | ||
|
||
@location = [] | ||
point_count = ZBar.zbar_symbol_get_loc_size(symbol) | ||
i = 0 | ||
while i < point_count | ||
@location << [ZBar.zbar_symbol_get_loc_x(symbol, i), ZBar.zbar_symbol_get_loc_y(symbol, i)] | ||
i += 1 | ||
end | ||
end | ||
end | ||
|
||
def ==(symbol) | ||
return false unless symbol.kind_of?(Symbol) | ||
|
||
( | ||
self.symbology == symbol.symbology && | ||
self.data == symbol.data && | ||
self.addon == symbol.addon && | ||
self.quality == symbol.quality && | ||
self.location == symbol.location | ||
) | ||
end | ||
end | ||
|
||
end |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,42 @@ | ||
require 'helper' | ||
|
||
class TestZbar < Test::Unit::TestCase | ||
should "probably rename this file and start testing for real" do | ||
flunk "hey buddy, you should probably rename this file and start testing for real" | ||
Path = File.dirname(__FILE__) | ||
|
||
class TestZBar < Test::Unit::TestCase | ||
should "read the right barcode from a PGM blob" do | ||
result = ZBar::Image.from_pgm(File.read("#{Path}/test.pgm")).process | ||
assert_equal(result.size, 1) | ||
assert_equal(result[0].data, '9876543210128') | ||
assert_equal(result[0].symbology, 'EAN-13') | ||
end | ||
|
||
should "read a barcode from a PGM file" do | ||
File.open("#{Path}/test.pgm") { |f| | ||
result = ZBar::Image.from_pgm(f).process | ||
assert_equal(result.size, 1) | ||
} | ||
end | ||
|
||
should "be able to re-use a processor" do | ||
processor = ZBar::Processor.new | ||
pgm = File.read("#{Path}/test.pgm") | ||
|
||
result1 = processor.process ZBar::Image.from_pgm(pgm) | ||
result2 = processor.process ZBar::Image.from_pgm(pgm) | ||
assert_equal(result1.size, 1) | ||
assert_equal(result2.size, 1) | ||
assert_equal(result1, result2) | ||
end | ||
|
||
should "read a barcode from a JPEG blob" do | ||
result = ZBar::Image.from_jpeg(File.read("#{Path}/test.jpg")).process | ||
assert_equal(result.size, 1) | ||
end | ||
|
||
should "read a barcode from a JPEG file" do | ||
File.open("#{Path}/test.jpg") { |f| | ||
result = ZBar::Image.from_jpeg(f).process | ||
assert_equal(result.size, 1) | ||
} | ||
end | ||
end |
Oops, something went wrong.