-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Requires zxing compiled library. A forthcoming homebrew formula is on its way.
- Loading branch information
0 parents
commit 7ae176a
Showing
21 changed files
with
372 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.rvmrc | ||
Gemfile.lock | ||
mkmf.log | ||
*.o | ||
tmp/ | ||
*.bundle | ||
Makefile |
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,2 @@ | ||
--format documentation | ||
--color |
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,2 @@ | ||
source :rubygems | ||
gemspec |
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 @@ | ||
|
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,10 @@ | ||
require 'rake/extensiontask' | ||
require "rspec/core/rake_task" | ||
|
||
Rake::ExtensionTask.new('qrdecoder_ext') do |ext| | ||
ext.lib_dir = 'lib/qrdecoder' | ||
end | ||
|
||
RSpec::Core::RakeTask.new | ||
|
||
task :default => [:clean, :compile, :spec] |
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,99 @@ | ||
/* | ||
* MagickBitmapSource.cpp | ||
* zxing | ||
* | ||
* Copyright 2010 ZXing authors All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include "MagickBitmapSource.h" | ||
|
||
#include <iostream> | ||
|
||
using namespace Magick; | ||
|
||
namespace zxing { | ||
|
||
MagickBitmapSource::MagickBitmapSource(Image& image) : image_(image) { | ||
width = (int)image.columns(); | ||
height = (int)image.rows(); | ||
|
||
pixel_cache = image.getConstPixels(0, 0, width, height); | ||
} | ||
|
||
MagickBitmapSource::~MagickBitmapSource() { | ||
|
||
} | ||
|
||
int MagickBitmapSource::getWidth() const { | ||
return width; | ||
} | ||
|
||
int MagickBitmapSource::getHeight() const { | ||
return height; | ||
} | ||
|
||
unsigned char* MagickBitmapSource::getRow(int y, unsigned char* row) { | ||
int width = getWidth(); | ||
if (row == NULL) { | ||
row = new unsigned char[width]; | ||
} | ||
for (int x = 0; x < width; x++) { | ||
const PixelPacket* p = pixel_cache + y * width + x; | ||
// We assume 16 bit values here | ||
// 0x200 = 1<<9, half an lsb of the result to force rounding | ||
row[x] = (unsigned char)((306 * ((int)p->red >> 8) + 601 * ((int)p->green >> 8) + | ||
117 * ((int)p->blue >> 8) + 0x200) >> 10); | ||
} | ||
return row; | ||
|
||
} | ||
|
||
/** This is a more efficient implementation. */ | ||
unsigned char* MagickBitmapSource::getMatrix() { | ||
int width = getWidth(); | ||
int height = getHeight(); | ||
unsigned char* matrix = new unsigned char[width*height]; | ||
unsigned char* m = matrix; | ||
const Magick::PixelPacket* p = pixel_cache; | ||
for (int y = 0; y < height; y++) { | ||
for (int x = 0; x < width; x++) { | ||
*m = (unsigned char)((306 * ((int)p->red >> 8) + 601 * ((int)p->green >> 8) + | ||
117 * ((int)p->blue >> 8) + 0x200) >> 10); | ||
m++; | ||
p++; | ||
} | ||
} | ||
return matrix; | ||
} | ||
|
||
bool MagickBitmapSource::isRotateSupported() const { | ||
return false; | ||
} | ||
|
||
Ref<LuminanceSource> MagickBitmapSource::rotateCounterClockwise() { | ||
//TODO(flyashi): add rotated image support. | ||
/* this segfaults. I tried a few things, none seemed to work. Perhaps the problem is elsewhere? */ | ||
/* | ||
Magick::Image rotated(image_); | ||
rotated.modifyImage(); | ||
rotated.rotate(90); // Image::rotate takes CCW degrees as an argument | ||
rotated.syncPixels(); | ||
return Ref<MagickBitmapSource> (new MagickBitmapSource(rotated)); | ||
*/ | ||
return Ref<MagickBitmapSource> (NULL); | ||
} | ||
|
||
} | ||
|
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,49 @@ | ||
#ifndef __MAGICK_BITMAP_SOURCE_H_ | ||
#define __MAGICK_BITMAP_SOURCE_H_ | ||
/* | ||
* MagickBitmapSource.h | ||
* zxing | ||
* | ||
* Copyright 2010 ZXing authors All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include <Magick++.h> | ||
#include <zxing/LuminanceSource.h> | ||
|
||
namespace zxing { | ||
|
||
class MagickBitmapSource : public LuminanceSource { | ||
private: | ||
Magick::Image& image_; | ||
int width; | ||
int height; | ||
const Magick::PixelPacket* pixel_cache; | ||
|
||
public: | ||
MagickBitmapSource(Magick::Image& image); | ||
|
||
~MagickBitmapSource(); | ||
|
||
int getWidth() const; | ||
int getHeight() const; | ||
unsigned char* getRow(int y, unsigned char* row); | ||
unsigned char* getMatrix(); | ||
bool isRotateSupported() const; | ||
Ref<LuminanceSource> rotateCounterClockwise(); | ||
}; | ||
|
||
} | ||
|
||
#endif /* MAGICKMONOCHROMEBITMAPSOURCE_H_ */ |
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,42 @@ | ||
require "mkmf" | ||
require "date" | ||
|
||
def exit_failure(msg) | ||
Logging::message msg | ||
message msg+"\n" | ||
exit(1) | ||
end | ||
|
||
# C++ flags | ||
cppflags = ENV["CPPFLAGS"] || $CPPFLAGS | ||
$CPPFLAGS = cppflags.to_s + " " + `Magick-config --cppflags`.chomp | ||
|
||
headers = %w{stdio.h stdlib.h math.h time.h} | ||
headers << "stdint.h" if have_header("stdint.h") | ||
headers << "sys/types.h" if have_header("sys/types.h") | ||
|
||
|
||
if have_header("wand/MagickWand.h") | ||
headers << "wand/MagickWand.h" | ||
else | ||
exit_failure "\nCan't install. Can't find MagickWand.h." | ||
end | ||
|
||
|
||
unless have_library("MagickCore", "InitializeMagick", headers) && have_library("Magick++","InitializeMagick",headers) | ||
exit_failure "Can't find the ImageMagick library or one of the dependent libraries. " + | ||
"Check the mkmf.log file for more detailed information.\n" | ||
end | ||
|
||
have_library("jpeg") | ||
have_library("zxing") | ||
|
||
have_func("snprintf", headers) | ||
|
||
have_struct_member("Image", "type", headers) | ||
have_type("MagickFunction", headers) | ||
have_type("ImageLayerMethod", headers) | ||
|
||
$defs = [] | ||
|
||
create_makefile("qrdecoder/qrdecoder_ext") |
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,64 @@ | ||
#include "ruby.h" | ||
|
||
#include <iostream> | ||
#include <fstream> | ||
#include <string> | ||
#include <Magick++.h> | ||
#include "MagickBitmapSource.h" | ||
#include <zxing/common/Counted.h> | ||
#include <zxing/qrcode/QRCodeReader.h> | ||
#include <zxing/Binarizer.h> | ||
#include <zxing/MultiFormatReader.h> | ||
#include <zxing/Result.h> | ||
#include <zxing/Reader.h> | ||
#include <zxing/ReaderException.h> | ||
#include <zxing/common/GlobalHistogramBinarizer.h> | ||
#include <zxing/common/HybridBinarizer.h> | ||
#include <exception> | ||
#include <zxing/Exception.h> | ||
#include <zxing/common/IllegalArgumentException.h> | ||
#include <zxing/BinaryBitmap.h> | ||
#include <zxing/DecodeHints.h> | ||
using namespace Magick; | ||
using namespace std; | ||
using namespace zxing; | ||
using namespace zxing::qrcode; | ||
|
||
|
||
VALUE mQRDecoder; | ||
|
||
extern "C" | ||
VALUE _decode(VALUE klass, VALUE path) { | ||
VALUE r_str; | ||
Image image; | ||
char *filepath = StringValueCStr(path); | ||
try { | ||
image.read(filepath); | ||
} catch (...) { | ||
rb_raise(rb_eIOError, "unable to read file"); | ||
cerr << "Unable to open image, ignoring" << filepath << endl; | ||
} | ||
try { | ||
Ref<MagickBitmapSource> source(new MagickBitmapSource(image)); | ||
|
||
Ref<Binarizer> binarizer(NULL); | ||
binarizer = new GlobalHistogramBinarizer(source); | ||
|
||
Ref<BinaryBitmap> image(new BinaryBitmap(binarizer)); | ||
Ref<Reader> reader(new MultiFormatReader); | ||
Ref<Result> result(reader->decode(image)); | ||
const char *str = result->getText()->getText().c_str(); | ||
r_str = rb_str_new2( str ); | ||
} catch (zxing::Exception& e) { | ||
r_str = Qnil; | ||
} | ||
|
||
return r_str; | ||
} | ||
|
||
extern "C" | ||
void Init_qrdecoder_ext() | ||
{ | ||
mQRDecoder = rb_define_module("QRDecoder"); | ||
rb_define_module_function(mQRDecoder, "decode", (VALUE(*)(...))_decode, 1); | ||
} |
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,5 @@ | ||
require 'qrdecoder/version' | ||
require 'qrdecoder/qrdecoder_ext' | ||
|
||
module QRDecoder | ||
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,3 @@ | ||
module QRDecoder | ||
VERSION = '0.0.1' | ||
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,29 @@ | ||
lib = File.expand_path('../lib/', __FILE__) | ||
$:.unshift lib unless $:.include?(lib) | ||
|
||
require 'qrdecoder/version' | ||
|
||
Gem::Specification.new do |s| | ||
s.version = QRDecoder::VERSION | ||
s.platform = Gem::Platform::RUBY | ||
|
||
s.name = "qrdecoder" | ||
s.summary = %Q{Wrapper around the C++ zxing library for decoding QR Codes} | ||
s.description = %Q{This Gem is a wrapper around an useful open-source library for decoding QR | ||
Codes, a two-dimensional bar code format popular in Japan created by the Denso-Wave Corporation in 1994.} | ||
s.email = ['josh@joshuadavey.com', 'dave@davelyon.net'] | ||
s.authors = ['Joshua Davey', 'Dave Lyon'] | ||
s.date = '2011-06-08' | ||
|
||
s.extensions = ["ext/qrdecoder_ext/extconf.rb"] | ||
|
||
s.extra_rdoc_files = ["README.rdoc", "ext/qrdecoder_ext/qrdecoder_ext.c"] | ||
s.files = Dir.glob("{bin,lib,ext}/**/*") + %w(History.txt README.rdoc) - ["lib/qrdecoder/qrdecoder_ext.bundle"] | ||
|
||
s.require_path = 'lib' | ||
s.required_rubygems_version = ">= 1.3.6" | ||
s.add_development_dependency "rspec", "~> 2.6.0" | ||
s.add_development_dependency "rake-compiler", "~> 0.7.5" | ||
|
||
s.test_files = Dir.glob("spec/**/*_spec.rb") + %w{spec/spec_helper.rb} | ||
end |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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,48 @@ | ||
require 'spec_helper' | ||
|
||
describe QRDecoder do | ||
describe ".decode" do | ||
subject { QRDecoder.decode(path) } | ||
context "with a path to a qrcode image" do | ||
context "with an encoded phrase" do | ||
let(:path) { qrcode_fixture("bacon.png") } | ||
it { should be_kind_of String } | ||
it { should == "Chunky Bacon!"} | ||
end | ||
context "with an encoded url" do | ||
let(:path) { qrcode_fixture("url.png") } | ||
it { should == "http://davelyon.net"} | ||
end | ||
context "with a large qrcode" do | ||
let(:path) { qrcode_fixture("big-url.png") } | ||
it { should == "http://joshuadavey.com"} | ||
end | ||
end | ||
context "with a non-qrcode image" do | ||
let(:path) { qrcode_fixture("image.png") } | ||
it { should == nil } | ||
end | ||
context "with a 'logoized' qrcode image" do | ||
let(:path) { qrcode_fixture("logo.jpg") } | ||
it { subject.strip.should == "http://www.celebrate-originality.jp/" } | ||
end | ||
context "with a 'colorized' qrcode image" do | ||
let(:path) { qrcode_fixture("colors.jpg") } | ||
it { subject.strip.should == "http://www.havas.com" } | ||
end | ||
context "with no arguments" do | ||
it "raises an error" do | ||
expect { | ||
QRDecoder.decode | ||
}.to raise_error(ArgumentError) | ||
end | ||
end | ||
context "with an invalid file type" do | ||
it "raises an error" do | ||
expect { | ||
QRDecoder.decode(__FILE__) | ||
}.to raise_error(IOError) | ||
end | ||
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,8 @@ | ||
require 'rubygems' | ||
require 'bundler/setup' | ||
require 'rspec' | ||
|
||
root = File.expand_path('../..', __FILE__) | ||
Dir["#{root}/spec/support/**/*.rb"].each {|f| require f} | ||
|
||
Bundler.require |
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,3 @@ | ||
def qrcode_fixture(name) | ||
File.expand_path("../data/#{name}", File.dirname(__FILE__)) | ||
end |