Did a special OneD mode for scanning UPC codes and the like. It uses a landscape...
[zxing.git] / iphone / ZXingWidget / ZXingWidgetController.m
index 6560d9a..3f709e3 100755 (executable)
 #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;
+@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;
@@ -54,6 +58,14 @@ CGImageRef UIGetScreenImage();
        return self;
 }
 
+- (void)dealloc {
+       if (beepSound != -1) {
+               AudioServicesDisposeSystemSoundID(beepSound);
+       }
+       [overlayView dealloc];
+       [super dealloc];
+}
+
 - (void)cancelled {
        NSLog(@"cancelled called in ZXingWidgetController");
        wasCancelled = true;
@@ -79,8 +91,19 @@ CGImageRef UIGetScreenImage();
        return false;
 }
 
+- (void)viewWillAppear:(BOOL)animated {
+       [super viewWillAppear:animated];
+       if ([self soundToPlay] != nil) {
+               OSStatus error = AudioServicesCreateSystemSoundID((CFURLRef)[self soundToPlay], &beepSound);
+               if (error != kAudioServicesNoError) {
+                       NSLog(@"Problem loading nearSound.caf");
+               }
+       }
+}
+
 - (void)viewDidAppear:(BOOL)animated {
     [super viewDidAppear:animated];
+       [overlayView setPoints:nil];
        wasCancelled = false;
        [NSTimer scheduledTimerWithTimeInterval: FIRST_TAKE_DELAY
                                                                         target: self
@@ -89,36 +112,129 @@ 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;
-       NSLog(@"crop rect %f, %f, %f, %f", cropRect.origin.x, cropRect.origin.y, cropRect.size.width, cropRect.size.height);
        [d decodeImage:scrn cropRect:cropRect];
 }
 
 // DecoderDelegate methods
 
 - (void)decoder:(Decoder *)decoder willDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset{
+#ifdef DEBUG
        NSLog(@"DecoderViewController MessageWhileDecodingWithDimensions: Decoding image (%.0fx%.0f) ...", image.size.width, image.size.height);
+#endif
 }
 
 - (void)decoder:(Decoder *)decoder
   decodingImage:(UIImage *)image
     usingSubset:(UIImage *)subset
        progress:(NSString *)message {
-       NSLog(@"decoding image %@", message);
 }
 
 - (void)presentResultForString:(NSString *)resultString {
-       NSLog(@"in presentResultForString()");
        self.result = [ResultParser parsedResultForString:resultString];
-       AudioServicesPlaySystemSound(beepSound);
-       //      self.actions = self.result.actions;
+       
+       if (beepSound != -1) {
+               AudioServicesPlaySystemSound(beepSound);
+       }
 #ifdef DEBUG
        NSLog(@"result string = %@", resultString);
        NSLog(@"result has %d actions", actions ? 0 : actions.count);
@@ -130,24 +246,22 @@ CGImageRef UIGetScreenImage();
                    forImage:(UIImage *)image
                 usingSubset:(UIImage *)subset {
        // simply add the points to the image view
-       NSLog(@"got points for display");
        [overlayView setPoints:resultPoints];
 }
 
 - (void)decoder:(Decoder *)decoder didDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset withResult:(TwoDDecoderResult *)twoDResult {
-       //      [self presentResultForString:twoDResult.text];
-       NSLog(@"decoded image!!");
+       [self presentResultForString:[twoDResult text]];
        [self presentResultPoints:[twoDResult points] forImage:image usingSubset:subset];
-       if (delegate != nil) {
-               [delegate scanResult:[twoDResult text]];
-       }
+       // now, in a selector, call the delegate to give this overlay time to show the points
+       [self performSelector:@selector(alertDelegate:) withObject:[[twoDResult text] copy] afterDelay:1.0];
        decoder.delegate = nil;
        [decoder release];
-       
-       // save the scan to the shared database
-       //      [[Database sharedDatabase] addScanWithText:twoDResult.text];
-       // need to call delegate....`
-       //      [self performResultAction:self];
+}
+
+- (void)alertDelegate:(id)text {       
+       if (delegate != nil) {
+               [delegate scanResult:text];
+       }
 }
 
 - (void)decoder:(Decoder *)decoder failedToDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset reason:(NSString *)reason {