QRコード読み取りソフト(ZXing)を使った簡単なアプリ



iPhoneで動く、オープンソースQRコード読み取りソフトとして ZXing ("Zebra Crossing") があります。このプロジェクトには iPhone 用のサンプルアプリ barcodes が入っていますが、色々な機能を持たせているのでQRコード読み取りライブラリーの使い方を知るには複雑すぎます。そこでカメラで画像を撮りQRコード読み取りを行う簡単なアプリを作ってみました。









サンプル アプリ

ZXingのQRコード読み取りライブラリー Decoder は Decoder.hのメソッドと、DecoderDelegate.hに定義されているデリゲートメソッドを以下の流れで使います。

  • Decodeの初期化は initWithNibName:bundle:内で行います
  • decodeImage:cropRect: メソッドで画像と画像の範囲を指定して読み取りを開始
  • decoder:didDecodeImage:usingSubset:withResult: 読み取りが成功するとこのメソッドが呼ばれます。読み取った結果はwithResult:に入っています。
  • decoder:failedToDecodeImage:usingSubset:reason: 読み取りが失敗するとこのメソッドが呼ばれます。
  • decoder:willDecodeImage:usingSubset: 読み取り開始時に呼ばれます。 usingSubsetは読み取りで使われる画像です。
  • decoder:decodingImage:usingSubset:progress: 読み取り中に呼び出され進行状況がわかります。


QRDecodeViewController.h

#import <UIKit/UIKit.h>
#import "Decoder.h"
#import "DecoderDelegate.h"
#import "ScannedImageView.h"
#import "TwoDDecoderResult.h"

@interface QRDecodeViewController : UIViewController <DecoderDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate> {
	IBOutlet ScannedImageView	*imageView;
	IBOutlet UILabel			*decodedText;
	Decoder *decoder;
}
@property (nonatomic, retain) Decoder *decoder;
@property (nonatomic, retain) ScannedImageView *imageView;

- (IBAction)onPushCapture:(id)sender;

@end

QRDecodeViewController.m (一部)

#import "QRDecodeViewController.h"

@implementation QRDecodeViewController

@synthesize imageView;
@synthesize decoder;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
	if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
		Decoder *d = [[Decoder alloc] init];
		self.decoder = d;
		d.delegate = self;
		[d release];
	}
	return self;
}


- (IBAction)onPushCapture:(id)sender {
	decodedText.text = @"";
	UIImagePickerController* picker = [[UIImagePickerController alloc] init];
        picker.sourceType = UIImagePickerControllerSourceTypeCamera;	
        picker.delegate = self;
	picker.allowsEditing = NO;
	    
        [self presentModalViewController:picker animated:NO];
}

- (void)decodeImage:(UIImage *)image {
	CGSize size = [image size];
	CGRect cropRect = CGRectMake(size.width / 4, size.height / 4, size.width / 2, size.height / 2);
	
	[image retain];
	[self.decoder decodeImage:image cropRect:cropRect];
	[image release];
}

- (void)imagePickerController:(UIImagePickerController *)picker
        didFinishPickingImage:(UIImage *)image
                  editingInfo:(NSDictionary *)editingInfo
{
	
	[[picker parentViewController] dismissModalViewControllerAnimated:NO];
	[self.imageView setImage:image];
	[self performSelector:@selector(decodeImage:) withObject:image afterDelay:0.2];
	decodedText.text = @"decoding...";
}

- (void)decoder:(Decoder *)decoder willDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset {
}

- (void)decoder:(Decoder *)decoder decodingImage:(UIImage *)image usingSubset:(UIImage *)subset
       progress:(NSString *)message {
}

- (void)decoder:(Decoder *)decoder didDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset 
        withResult:(TwoDDecoderResult *)twoDResult {
	[self.imageView setImage:subset];
	decodedText.text = twoDResult.text;
}

- (void)decoder:(Decoder *)decoder failedToDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset
        reason:(NSString *)reason {
	[self.imageView setImage:subset];
	decodedText.text = @"Failed to decode";
}

ZXing から QR Decoder の切り出し方法

  • QR Decoder本体 cpp/core をプロジェクトにコピーします。今回は CoreSrc というグループにしました このソースが参照出来るように includeのパスを設定します。
  • QR Decoder は xzingcore という static library にします。そのライブラリを アプリの依存関係に指定します。
  • QR Decoder から Objective-Cのソース TwoDDecoderResult、ScannedImageView、Decoder、DecoderDelegate、GrayBytesMonochromeBitmapSource をコピーします。
  • Decoder.m は Decoder.mm にしないとエラーが出ました。ZXingでは出てないので何か設定が抜けているのかも
  • iPhone SDK にある libiconv2.dylib を Framework に追加


一昨日に行ったので少し抜けてるかもしれません。上手く行かなかったらコメント下さい。