mirror of
https://github.com/zxing/zxing.git
synced 2025-01-13 04:07:27 -08:00
Did a special OneD mode for scanning UPC codes and the like. It uses a landscape scan UI with a red line (and green line highlighting the decoded area). Must set it explictly in the ScanTest - where the ZXingWidget is created.
git-svn-id: https://zxing.googlecode.com/svn/trunk@1370 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
2f7ca668fc
commit
4b2e92b9c4
|
@ -18,7 +18,10 @@
|
|||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
[self setTitle:@"ZXing"];
|
||||
scanController = [[ZXingWidgetController alloc] initWithDelegate:self];
|
||||
scanController = [ZXingWidgetController alloc];
|
||||
[scanController setOneDMode:false];
|
||||
[scanController setShowCancel:true];
|
||||
scanController = [scanController initWithDelegate:self];
|
||||
NSBundle *mainBundle = [NSBundle mainBundle];
|
||||
[scanController setSoundToPlay:[[NSURL fileURLWithPath:[mainBundle pathForResource:@"beep-beep" ofType:@"aiff"] isDirectory:NO] retain]];
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ using namespace zxing;
|
|||
|
||||
self.subsetImage = [UIImage imageWithCGImage:subsetImageRef];
|
||||
// for debug purposes.
|
||||
UIImageWriteToSavedPhotosAlbum(self.subsetImage, nil, nil, nil);
|
||||
// UIImageWriteToSavedPhotosAlbum(self.subsetImage, nil, nil, nil);
|
||||
|
||||
CGImageRelease(subsetImageRef);
|
||||
|
||||
|
@ -161,7 +161,7 @@ using namespace zxing;
|
|||
TwoDDecoderResult *decoderResult = nil;
|
||||
|
||||
#ifdef TRY_ROTATIONS
|
||||
for (int i = 0; !decoderResult && i < 4; i++) {`
|
||||
for (int i = 0; !decoderResult && i < 4; i++) {
|
||||
#endif
|
||||
for (FormatReader *reader in formatReaders) {
|
||||
try {
|
||||
|
|
|
@ -40,7 +40,6 @@ static NSMutableSet *sFormatReaders = nil;
|
|||
@synchronized(self) {
|
||||
|
||||
formatReaders = [[sFormatReaders copy] autorelease];
|
||||
NSLog(@"readers : %d",[formatReaders count]);
|
||||
}
|
||||
return formatReaders;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
+ (void)load {
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSLog(@"MultiFormatReader: load called");
|
||||
[FormatReader registerFormatReader:[[[self alloc] init] autorelease]];
|
||||
[pool drain];
|
||||
}
|
||||
|
|
|
@ -23,11 +23,13 @@
|
|||
NSArray *_points;
|
||||
UIButton *cancelButton;
|
||||
id<CancelDelegate> delegate;
|
||||
BOOL oneDMode;
|
||||
}
|
||||
|
||||
//@property (nonatomic, retain) UIImage* image;
|
||||
@property (nonatomic, retain) NSArray* points;
|
||||
@property (nonatomic, assign) id<CancelDelegate> delegate;
|
||||
@property (nonatomic, assign) BOOL oneDMode;
|
||||
|
||||
- (id)initWithCancelEnabled:(BOOL)cancelEnabled frame:(CGRect)frame;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ static const CGFloat kPadding = 10;
|
|||
|
||||
@implementation OverlayView
|
||||
|
||||
@synthesize delegate;
|
||||
@synthesize delegate, oneDMode;
|
||||
@synthesize points = _points;
|
||||
//@synthesize image;
|
||||
|
||||
|
@ -33,7 +33,14 @@ static const CGFloat kPadding = 10;
|
|||
if (cancelEnabled) {
|
||||
cancelButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
|
||||
[cancelButton setTitle:@"Cancel" forState:UIControlStateNormal];
|
||||
[cancelButton setFrame:CGRectMake(95, 420, 130, 45)];
|
||||
if (oneDMode) {
|
||||
[cancelButton setTransform:CGAffineTransformMakeRotation(M_PI/2)];
|
||||
[cancelButton setFrame:CGRectMake(20, 175, 45, 130)];
|
||||
}
|
||||
else {
|
||||
[cancelButton setFrame:CGRectMake(95, 420, 130, 45)];
|
||||
}
|
||||
|
||||
[cancelButton addTarget:self action:@selector(cancel:) forControlEvents:UIControlEventTouchUpInside];
|
||||
[self addSubview:cancelButton];
|
||||
}
|
||||
|
@ -53,7 +60,7 @@ static const CGFloat kPadding = 10;
|
|||
imageView = nil;
|
||||
[_points release];
|
||||
_points = nil;
|
||||
|
||||
[cancelButton release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
@ -86,28 +93,57 @@ static const CGFloat kPadding = 10;
|
|||
[self drawRect:cropRect inContext:c];
|
||||
|
||||
// CGContextSetStrokeColor(c, white);
|
||||
char *text = "Place a barcode inside the";
|
||||
char *text2 = "viewfinder rectangle to scan it.";
|
||||
// CGContextSetStrokeColor(c, white);
|
||||
CGContextSaveGState(c);
|
||||
CGContextSelectFont(c, "Helvetica", 18, kCGEncodingMacRoman);
|
||||
CGContextScaleCTM(c, -1.0, 1.0);
|
||||
CGContextRotateCTM(c, 3.1415);
|
||||
CGContextShowTextAtPoint(c, 48.0, -45.0, text, 26);
|
||||
CGContextShowTextAtPoint(c, 33.0, -70.0, text2, 32);
|
||||
if (oneDMode) {
|
||||
char *text = "Place a red line over the bar code to be scanned.";
|
||||
CGContextSelectFont(c, "Helvetica", 15, kCGEncodingMacRoman);
|
||||
CGContextScaleCTM(c, -1.0, 1.0);
|
||||
CGContextRotateCTM(c, M_PI/2);
|
||||
CGContextShowTextAtPoint(c, 74.0, 285.0, text, 49);
|
||||
}
|
||||
else {
|
||||
char *text = "Place a barcode inside the";
|
||||
char *text2 = "viewfinder rectangle to scan it.";
|
||||
CGContextSelectFont(c, "Helvetica", 18, kCGEncodingMacRoman);
|
||||
CGContextScaleCTM(c, -1.0, 1.0);
|
||||
CGContextRotateCTM(c, M_PI);
|
||||
CGContextShowTextAtPoint(c, 48.0, -45.0, text, 26);
|
||||
CGContextShowTextAtPoint(c, 33.0, -70.0, text2, 32);
|
||||
}
|
||||
CGContextRestoreGState(c);
|
||||
int offset = rect.size.width / 2;
|
||||
if (oneDMode) {
|
||||
CGFloat red[4] = {1.0f, 0.0f, 0.0f, 1.0f};
|
||||
CGContextSetStrokeColor(c, red);
|
||||
CGContextSetFillColor(c, red);
|
||||
CGContextBeginPath(c);
|
||||
// CGContextMoveToPoint(c, rect.origin.x + kPadding, rect.origin.y + offset);
|
||||
// CGContextAddLineToPoint(c, rect.origin.x + rect.size.width - kPadding, rect.origin.y + offset);
|
||||
CGContextMoveToPoint(c, rect.origin.x + offset, rect.origin.y + kPadding);
|
||||
CGContextAddLineToPoint(c, rect.origin.x + offset, rect.origin.y + rect.size.height - kPadding);
|
||||
CGContextStrokePath(c);
|
||||
}
|
||||
if( nil != _points ) {
|
||||
CGFloat blue[4] = {0.0f, 1.0f, 0.0f, 1.0f};
|
||||
CGContextSetStrokeColor(c, blue);
|
||||
CGContextSetFillColor(c, blue);
|
||||
CGRect smallSquare = CGRectMake(0, 0, 10, 10);
|
||||
for( NSValue* value in _points ) {
|
||||
CGPoint point = [value CGPointValue];
|
||||
NSLog(@"drawing point at %f, %f", point.x, point.y);
|
||||
smallSquare.origin = CGPointMake(
|
||||
cropRect.origin.x + point.x - smallSquare.size.width / 2,
|
||||
cropRect.origin.y + point.y - smallSquare.size.height / 2);
|
||||
[self drawRect:smallSquare inContext:c];
|
||||
if (oneDMode) {
|
||||
CGPoint val1 = [[_points objectAtIndex:0] CGPointValue];
|
||||
CGPoint val2 = [[_points objectAtIndex:1] CGPointValue];
|
||||
CGContextMoveToPoint(c, offset, val1.x);
|
||||
CGContextAddLineToPoint(c, offset, val2.x);
|
||||
CGContextStrokePath(c);
|
||||
}
|
||||
else {
|
||||
CGRect smallSquare = CGRectMake(0, 0, 10, 10);
|
||||
for( NSValue* value in _points ) {
|
||||
CGPoint point = [value CGPointValue];
|
||||
smallSquare.origin = CGPointMake(
|
||||
cropRect.origin.x + point.x - smallSquare.size.width / 2,
|
||||
cropRect.origin.y + point.y - smallSquare.size.height / 2);
|
||||
[self drawRect:smallSquare inContext:c];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -145,8 +181,13 @@ static const CGFloat kPadding = 10;
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
- (CGRect) cropRect {
|
||||
CGFloat rectSize = self.frame.size.width - kPadding * 2;
|
||||
|
||||
return CGRectMake(kPadding, (self.frame.size.height - rectSize) / 2, rectSize, rectSize);
|
||||
if (!oneDMode) {
|
||||
return CGRectMake(kPadding, (self.frame.size.height - rectSize) / 2, rectSize, rectSize);
|
||||
}
|
||||
else {
|
||||
CGFloat rectSize2 = self.frame.size.height - kPadding * 2;
|
||||
return CGRectMake(kPadding, kPadding, rectSize, rectSize2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,11 +31,13 @@
|
|||
NSURL *soundToPlay;
|
||||
id<ZXingDelegate> delegate;
|
||||
BOOL wasCancelled;
|
||||
BOOL oneDMode;
|
||||
}
|
||||
|
||||
@property (nonatomic, assign) id<ZXingDelegate> delegate;
|
||||
@property (nonatomic, assign) BOOL showCancel;
|
||||
@property (nonatomic, assign) NSURL *soundToPlay;
|
||||
@property (nonatomic, assign) BOOL oneDMode;
|
||||
@property (nonatomic, retain) ParsedResult *result;
|
||||
@property (nonatomic, retain) NSArray *actions;
|
||||
|
||||
|
|
|
@ -22,29 +22,32 @@
|
|||
#import "ResultAction.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include "UKImage.h"
|
||||
|
||||
#define CAMERA_SCALAR 1.12412 // scalar = (480 / (2048 / 480))
|
||||
#define FIRST_TAKE_DELAY 1.0
|
||||
#define ONE_D_BAND_HEIGHT 10.0
|
||||
|
||||
CGImageRef UIGetScreenImage();
|
||||
|
||||
@implementation ZXingWidgetController
|
||||
@synthesize result, actions, showCancel, delegate, soundToPlay;
|
||||
@synthesize result, actions, showCancel, delegate, soundToPlay, oneDMode;
|
||||
|
||||
- (id)initWithDelegate:(id<ZXingDelegate>)scanDelegate {
|
||||
if (self = [super init]) {
|
||||
[self setDelegate:scanDelegate];
|
||||
showCancel = true;
|
||||
beepSound = -1;
|
||||
self.wantsFullScreenLayout = YES;
|
||||
self.sourceType = UIImagePickerControllerSourceTypeCamera;
|
||||
float zoomFactor = CAMERA_SCALAR;
|
||||
if ([self fixedFocus]) {
|
||||
zoomFactor *= 1.5;
|
||||
zoomFactor *= 2.0;
|
||||
}
|
||||
self.cameraViewTransform = CGAffineTransformScale(
|
||||
self.cameraViewTransform, zoomFactor, zoomFactor);
|
||||
overlayView = [[OverlayView alloc] initWithCancelEnabled:showCancel frame:[UIScreen mainScreen].bounds];
|
||||
overlayView = [OverlayView alloc];
|
||||
[overlayView setOneDMode:oneDMode];
|
||||
overlayView = [overlayView initWithCancelEnabled:showCancel frame:[UIScreen mainScreen].bounds];
|
||||
[overlayView setDelegate:self];
|
||||
self.sourceType = UIImagePickerControllerSourceTypeCamera;
|
||||
self.showsCameraControls = NO;
|
||||
|
@ -90,9 +93,7 @@ CGImageRef UIGetScreenImage();
|
|||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
NSLog(@"should load sound");
|
||||
if ([self soundToPlay] != nil) {
|
||||
NSLog(@"will try to load sound");
|
||||
OSStatus error = AudioServicesCreateSystemSoundID((CFURLRef)[self soundToPlay], &beepSound);
|
||||
if (error != kAudioServicesNoError) {
|
||||
NSLog(@"Problem loading nearSound.caf");
|
||||
|
@ -111,12 +112,104 @@ CGImageRef UIGetScreenImage();
|
|||
repeats: NO];
|
||||
}
|
||||
|
||||
- (CGImageRef)CGImageRotated90:(CGImageRef)imgRef
|
||||
{
|
||||
CGFloat angleInRadians = -90 * (M_PI / 180);
|
||||
CGFloat width = CGImageGetWidth(imgRef);
|
||||
CGFloat height = CGImageGetHeight(imgRef);
|
||||
|
||||
CGRect imgRect = CGRectMake(0, 0, width, height);
|
||||
CGAffineTransform transform = CGAffineTransformMakeRotation(angleInRadians);
|
||||
CGRect rotatedRect = CGRectApplyAffineTransform(imgRect, transform);
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGContextRef bmContext = CGBitmapContextCreate(NULL,
|
||||
rotatedRect.size.width,
|
||||
rotatedRect.size.height,
|
||||
8,
|
||||
0,
|
||||
colorSpace,
|
||||
kCGImageAlphaPremultipliedFirst);
|
||||
CGContextSetAllowsAntialiasing(bmContext, FALSE);
|
||||
CGContextSetInterpolationQuality(bmContext, kCGInterpolationNone);
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
// CGContextTranslateCTM(bmContext,
|
||||
// +(rotatedRect.size.width/2),
|
||||
// +(rotatedRect.size.height/2));
|
||||
CGContextScaleCTM(bmContext, rotatedRect.size.width/rotatedRect.size.height, 1.0);
|
||||
CGContextTranslateCTM(bmContext, 0.0, rotatedRect.size.height);
|
||||
CGContextRotateCTM(bmContext, angleInRadians);
|
||||
// CGContextTranslateCTM(bmContext,
|
||||
// -(rotatedRect.size.width/2),
|
||||
// -(rotatedRect.size.height/2));
|
||||
CGContextDrawImage(bmContext, CGRectMake(0, 0,
|
||||
rotatedRect.size.width,
|
||||
rotatedRect.size.height),
|
||||
imgRef);
|
||||
|
||||
CGImageRef rotatedImage = CGBitmapContextCreateImage(bmContext);
|
||||
CFRelease(bmContext);
|
||||
[(id)rotatedImage autorelease];
|
||||
|
||||
return rotatedImage;
|
||||
}
|
||||
|
||||
- (CGImageRef)CGImageRotated180:(CGImageRef)imgRef
|
||||
{
|
||||
CGFloat angleInRadians = M_PI;
|
||||
CGFloat width = CGImageGetWidth(imgRef);
|
||||
CGFloat height = CGImageGetHeight(imgRef);
|
||||
|
||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
CGContextRef bmContext = CGBitmapContextCreate(NULL,
|
||||
width,
|
||||
height,
|
||||
8,
|
||||
0,
|
||||
colorSpace,
|
||||
kCGImageAlphaPremultipliedFirst);
|
||||
CGContextSetAllowsAntialiasing(bmContext, FALSE);
|
||||
CGContextSetInterpolationQuality(bmContext, kCGInterpolationNone);
|
||||
CGColorSpaceRelease(colorSpace);
|
||||
CGContextTranslateCTM(bmContext,
|
||||
+(width/2),
|
||||
+(height/2));
|
||||
CGContextRotateCTM(bmContext, angleInRadians);
|
||||
CGContextTranslateCTM(bmContext,
|
||||
-(width/2),
|
||||
-(height/2));
|
||||
CGContextDrawImage(bmContext, CGRectMake(0, 0, width, height), imgRef);
|
||||
|
||||
CGImageRef rotatedImage = CGBitmapContextCreateImage(bmContext);
|
||||
CFRelease(bmContext);
|
||||
[(id)rotatedImage autorelease];
|
||||
|
||||
return rotatedImage;
|
||||
}
|
||||
|
||||
- (void)takePicture:(NSTimer*)theTimer {
|
||||
CGImageRef capture = UIGetScreenImage();
|
||||
UIImage *scrn = [UIImage imageWithCGImage:CGImageCreateWithImageInRect(capture, [overlayView cropRect])];
|
||||
CGRect cropRect = [overlayView cropRect];
|
||||
if (oneDMode) {
|
||||
// let's just give the decoder a vertical band right above the red line
|
||||
cropRect.origin.x = cropRect.origin.x + (cropRect.size.width / 2) - (ONE_D_BAND_HEIGHT + 1);
|
||||
cropRect.size.width = ONE_D_BAND_HEIGHT;
|
||||
// do a rotate
|
||||
CGImageRef croppedImg = CGImageCreateWithImageInRect(capture, cropRect);
|
||||
CGImageRelease(capture);
|
||||
capture = [self CGImageRotated90:croppedImg];
|
||||
capture = [self CGImageRotated180:capture];
|
||||
// UIImageWriteToSavedPhotosAlbum([UIImage imageWithCGImage:capture], nil, nil, nil);
|
||||
CGImageRelease(croppedImg);
|
||||
cropRect.origin.x = 0.0;
|
||||
cropRect.origin.y = 0.0;
|
||||
cropRect.size.width = CGImageGetWidth(capture);
|
||||
cropRect.size.height = CGImageGetHeight(capture);
|
||||
}
|
||||
|
||||
UIImage *scrn = [UIImage imageWithCGImage:CGImageCreateWithImageInRect(capture, cropRect)];
|
||||
Decoder *d = [[Decoder alloc] init];
|
||||
d.delegate = self;
|
||||
CGRect cropRect = overlayView.cropRect;
|
||||
cropRect.origin.x = 0.0;
|
||||
cropRect.origin.y = 0.0;
|
||||
[d decodeImage:scrn cropRect:cropRect];
|
||||
|
@ -140,7 +233,6 @@ CGImageRef UIGetScreenImage();
|
|||
self.result = [ResultParser parsedResultForString:resultString];
|
||||
|
||||
if (beepSound != -1) {
|
||||
NSLog(@"about to play beep... trying...");
|
||||
AudioServicesPlaySystemSound(beepSound);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
|
|
Loading…
Reference in a new issue