Skip to content
This repository has been archived by the owner on Aug 11, 2020. It is now read-only.

Commit

Permalink
Add QR code encoder implementation for IOS
Browse files Browse the repository at this point in the history
  • Loading branch information
smlu authored and Ryan Willoughby committed Mar 30, 2015
1 parent a1f216d commit 8b10b8a
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 12 deletions.
2 changes: 2 additions & 0 deletions plugin.xml
Expand Up @@ -39,6 +39,8 @@
<framework src="AssetsLibrary.framework" />
<framework src="CoreVideo.framework" />
<framework src="QuartzCore.framework" />
<framework src="CoreGraphics.framework" />
<framework src="CoreImage.framework" />
</platform>

<!-- android -->
Expand Down
139 changes: 127 additions & 12 deletions src/ios/CDVBarcodeScanner.mm
Expand Up @@ -15,13 +15,11 @@
// use the all-in-one version of zxing that we built
//------------------------------------------------------------------------------
#import "zxing-all-in-one.h"

#import <Cordova/CDVPlugin.h>


//------------------------------------------------------------------------------
// Delegate to handle orientation functions
//
//------------------------------------------------------------------------------
@protocol CDVBarcodeScannerOrientationDelegate <NSObject>

Expand All @@ -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
Expand Down Expand Up @@ -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
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -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 )
{
Expand Down Expand Up @@ -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];
}

//--------------------------------------------------------------------------
Expand Down Expand Up @@ -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) {
Expand All @@ -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";
Expand Down Expand Up @@ -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
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -649,7 +765,7 @@ - (void)dealloc {
// self.processor = nil;
self.shutterPressed = NO;
self.alternateXib = nil;
self.overlayView = nil;
self.overlayView = nil;
[super dealloc];
}

Expand Down Expand Up @@ -710,7 +826,7 @@ - (void)flipCameraButtonPressed:(id)sender
}

//--------------------------------------------------------------------------
- (UIView *)buildOverlayViewFromXib
- (UIView *)buildOverlayViewFromXib
{
[[NSBundle mainBundle] loadNibNamed:self.alternateXib owner:self options:NULL];

Expand All @@ -720,7 +836,7 @@ - (UIView *)buildOverlayViewFromXib
return nil;
}

return self.overlayView;
return self.overlayView;
}

//--------------------------------------------------------------------------
Expand Down Expand Up @@ -759,7 +875,6 @@ - (UIView*)buildOverlayView {
target:(id)self
action:@selector(flipCameraButtonPressed:)
];


#if USE_SHUTTER
id shutterButton = [[UIBarButtonItem alloc]
Expand Down Expand Up @@ -858,7 +973,7 @@ - (UIImage*)buildReticleImage {
#pragma mark CDVBarcodeScannerOrientationDelegate

- (BOOL)shouldAutorotate
{
{
return NO;
}

Expand Down

0 comments on commit 8b10b8a

Please sign in to comment.