diff --git a/plugin.xml b/plugin.xml index 6a7f2165..75f7cf00 100644 --- a/plugin.xml +++ b/plugin.xml @@ -39,6 +39,8 @@ + + diff --git a/src/ios/CDVBarcodeScanner.mm b/src/ios/CDVBarcodeScanner.mm index 35253fe4..9a38a551 100644 --- a/src/ios/CDVBarcodeScanner.mm +++ b/src/ios/CDVBarcodeScanner.mm @@ -15,13 +15,11 @@ // use the all-in-one version of zxing that we built //------------------------------------------------------------------------------ #import "zxing-all-in-one.h" - #import //------------------------------------------------------------------------------ // Delegate to handle orientation functions -// //------------------------------------------------------------------------------ @protocol CDVBarcodeScannerOrientationDelegate @@ -48,6 +46,7 @@ @interface CDVBarcodeScanner : CDVPlugin {} - (NSString*)isScanNotPossible; - (void)scan:(CDVInvokedUrlCommand*)command; - (void)encode:(CDVInvokedUrlCommand*)command; +- (void)returnImage:(NSString*)filePath callback:(NSString*)callback; - (void)returnSuccess:(NSString*)scannedText format:(NSString*)format cancelled:(BOOL)cancelled flipped:(BOOL)flipped callback:(NSString*)callback; - (void)returnError:(NSString*)message callback:(NSString*)callback; @end @@ -85,6 +84,19 @@ - (UIImage*) getImageFromLuminanceSource:(zxing::LuminanceSource*)luminanceSourc - (void)dumpImage:(UIImage*)image; @end +//------------------------------------------------------------------------------ +// Qr encoder processor +//------------------------------------------------------------------------------ +@interface CDVqrProcessor: NSObject +@property (nonatomic, retain) CDVBarcodeScanner* plugin; +@property (nonatomic, retain) NSString* callback; +@property (nonatomic, retain) NSString* stringToEncode; +@property NSInteger size; + +- (id)initWithPlugin:(CDVBarcodeScanner*)plugin callback:(NSString*)callback stringToEncode:(NSString*)stringToEncode; +- (void)generateImage; +@end + //------------------------------------------------------------------------------ // view controller for the ui //------------------------------------------------------------------------------ @@ -130,7 +142,7 @@ - (void)scan:(CDVInvokedUrlCommand*)command { callback = command.callbackId; - // We allow the user to define an alternate xib file for loading the overlay. + // We allow the user to define an alternate xib file for loading the overlay. NSString *overlayXib = nil; if ( [command.arguments count] >= 1 ) { @@ -158,7 +170,33 @@ - (void)scan:(CDVInvokedUrlCommand*)command { //-------------------------------------------------------------------------- - (void)encode:(CDVInvokedUrlCommand*)command { - [self returnError:@"encode function not supported" callback:command.callbackId]; + if([command.arguments count] < 1) + [self returnError:@"Too few arguments!" callback:command.callbackId]; + + CDVqrProcessor* processor; + NSString* callback; + callback = command.callbackId; + + processor = [[CDVqrProcessor alloc] + initWithPlugin:self + callback:callback + stringToEncode: command.arguments[0][@"data"] + ]; + + [processor retain]; + [processor retain]; + [processor retain]; + // queue [processor generateImage] to run on the event loop + [processor performSelector:@selector(generateImage) withObject:nil afterDelay:0]; +} + +- (void)returnImage:(NSString*)filePath callback:(NSString*)callback{ + CDVPluginResult* result = [CDVPluginResult + resultWithStatus: CDVCommandStatus_OK + messageAsString:filePath + ]; + + [[self commandDelegate] sendPluginResult:result callbackId:callback]; } //-------------------------------------------------------------------------- @@ -315,9 +353,9 @@ - (NSString*)setUpCaptureSession { AVCaptureSession* captureSession = [[AVCaptureSession alloc] init]; self.captureSession = captureSession; - AVCaptureDevice* __block device = nil; + AVCaptureDevice* __block device = nil; if (self.isFrontCamera) { - + NSArray* devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; [devices enumerateObjectsUsingBlock:^(AVCaptureDevice *obj, NSUInteger idx, BOOL *stop) { if (obj.position == AVCaptureDevicePositionFront) { @@ -329,7 +367,7 @@ - (NSString*)setUpCaptureSession { if (!device) return @"unable to obtain video capture device"; } - + AVCaptureDeviceInput* input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error]; if (!input) return @"unable to obtain video capture device input"; @@ -622,6 +660,84 @@ - (void)dumpImage:(UIImage*)image { @end +//------------------------------------------------------------------------------ +// qr encoder processor +//------------------------------------------------------------------------------ +@implementation CDVqrProcessor +@synthesize plugin = _plugin; +@synthesize callback = _callback; +@synthesize stringToEncode = _stringToEncode; +@synthesize size = _size; + +- (id)initWithPlugin:(CDVBarcodeScanner*)plugin callback:(NSString*)callback stringToEncode:(NSString*)stringToEncode{ + self = [super init]; + if (!self) return self; + + self.plugin = plugin; + self.callback = callback; + self.stringToEncode = stringToEncode; + self.size = 300; + + return self; +} + +//-------------------------------------------------------------------------- +- (void)dealloc { + self.plugin = nil; + self.callback = nil; + self.stringToEncode = nil; + + [super dealloc]; +} +//-------------------------------------------------------------------------- +- (void)generateImage{ + /* setup qr filter */ + CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"]; + [filter setDefaults]; + + /* set filter's input message + * the encoding string has to be convert to a UTF-8 encoded NSData object */ + [filter setValue:[self.stringToEncode dataUsingEncoding:NSUTF8StringEncoding] + forKey:@"inputMessage"]; + + /* on ios >= 7.0 set low image error correction level */ + if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_7_0) + [filter setValue:@"L" forKey:@"inputCorrectionLevel"]; + + /* prepare cgImage */ + CIImage *outputImage = [filter outputImage]; + CIContext *context = [CIContext contextWithOptions:nil]; + CGImageRef cgImage = [context createCGImage:outputImage + fromRect:[outputImage extent]]; + + /* returned qr code image */ + UIImage *qrImage = [UIImage imageWithCGImage:cgImage + scale:1. + orientation:UIImageOrientationUp]; + /* resize generated image */ + CGFloat width = _size; + CGFloat height = _size; + + UIGraphicsBeginImageContext(CGSizeMake(width, height)); + + CGContextRef ctx = UIGraphicsGetCurrentContext(); + CGContextSetInterpolationQuality(ctx, kCGInterpolationNone); + [qrImage drawInRect:CGRectMake(0, 0, width, height)]; + qrImage = UIGraphicsGetImageFromCurrentImageContext(); + + /* clean up */ + UIGraphicsEndImageContext(); + CGImageRelease(cgImage); + + /* save image to file */ + NSString* filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"tmpqrcode.jpeg"]; + [UIImageJPEGRepresentation(qrImage, 1.0) writeToFile:filePath atomically:YES]; + + /* return file path back to cordova */ + [self.plugin returnImage:filePath callback: self.callback]; +} +@end + //------------------------------------------------------------------------------ // view controller for the ui //------------------------------------------------------------------------------ @@ -649,7 +765,7 @@ - (void)dealloc { // self.processor = nil; self.shutterPressed = NO; self.alternateXib = nil; - self.overlayView = nil; + self.overlayView = nil; [super dealloc]; } @@ -710,7 +826,7 @@ - (void)flipCameraButtonPressed:(id)sender } //-------------------------------------------------------------------------- -- (UIView *)buildOverlayViewFromXib +- (UIView *)buildOverlayViewFromXib { [[NSBundle mainBundle] loadNibNamed:self.alternateXib owner:self options:NULL]; @@ -720,7 +836,7 @@ - (UIView *)buildOverlayViewFromXib return nil; } - return self.overlayView; + return self.overlayView; } //-------------------------------------------------------------------------- @@ -759,7 +875,6 @@ - (UIView*)buildOverlayView { target:(id)self action:@selector(flipCameraButtonPressed:) ]; - #if USE_SHUTTER id shutterButton = [[UIBarButtonItem alloc] @@ -858,7 +973,7 @@ - (UIImage*)buildReticleImage { #pragma mark CDVBarcodeScannerOrientationDelegate - (BOOL)shouldAutorotate -{ +{ return NO; }