diff --git a/README.md b/README.md index 2a777ba9a..1531359f0 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ The following barcode types are currently supported: * AZTEC * PDF417 -`success` and `fail` are callback functions. Success is passed an object with data, type and cancelled properties. Data is the text representation of the barcode data, type is the type of barcode detected and cancelled is whether or not the user cancelled the scan. +`success` and `fail` are callback functions. Success is passed an object with data, type and cancelled properties. Data is the text representation of the barcode data, type is the type of barcode detected and cancelled is whether or not the user cancelled the scan. In iOS you also get the successfully last-scanned image as base64 string in the success callback. A full example could be: ``` @@ -96,6 +96,11 @@ A full example could be: "Result: " + result.text + "\n" + "Format: " + result.format + "\n" + "Cancelled: " + result.cancelled); + + // Use image in which the code was recognized in DOM + var scanImage = document.querySelector("#scanImage"); + scanImage.setAttribute( 'src', result.scanImage ); + }, function (error) { alert("Scanning failed: " + error); diff --git a/src/ios/CDVBarcodeScanner.mm b/src/ios/CDVBarcodeScanner.mm index d57bfa1b4..8e8e2d9ff 100644 --- a/src/ios/CDVBarcodeScanner.mm +++ b/src/ios/CDVBarcodeScanner.mm @@ -48,7 +48,7 @@ @interface CDVBarcodeScanner : CDVPlugin {} - (NSString*)isScanNotPossible; - (void)scan:(CDVInvokedUrlCommand*)command; - (void)encode:(CDVInvokedUrlCommand*)command; -- (void)returnSuccess:(NSString*)scannedText format:(NSString*)format cancelled:(BOOL)cancelled flipped:(BOOL)flipped callback:(NSString*)callback; +- (void)returnSuccess:(NSString*)scannedText format:(NSString*)format scanImage:(NSString*)imageBase64 cancelled:(BOOL)cancelled flipped:(BOOL)flipped callback:(NSString*)callback; - (void)returnError:(NSString*)message callback:(NSString*)callback; @end @@ -72,7 +72,7 @@ @interface CDVbcsProcessor : NSObject getText().c_str(); NSString* resultString = [[[NSString alloc] initWithCString:cString encoding:NSUTF8StringEncoding] autorelease]; - [self barcodeScanSucceeded:resultString format:format]; + //DEBUG: Dump succeeded image to Photos + //UIImage *image= [[self getImageFromSample:sampleBuffer] autorelease]; + //[self dumpImage: image]; + + // Write base64 to Javascript + UIImage *image= [[self getImageFromSample:sampleBuffer] autorelease]; + NSString *imageBase64 = @"data:image/jpeg;base64,"; + imageBase64 = [imageBase64 stringByAppendingString:[UIImagePNGRepresentation(image) base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]]; + + [self barcodeScanSucceeded:resultString format:format scanImage:imageBase64]; } catch (zxing::ReaderException &rex) { @@ -488,6 +506,11 @@ - (NSString*)formatStringFrom:(zxing::BarcodeFormat)format { if (format == zxing::BarcodeFormat_CODE_128) return @"CODE_128"; if (format == zxing::BarcodeFormat_CODE_39) return @"CODE_39"; if (format == zxing::BarcodeFormat_ITF) return @"ITF"; + if (format == zxing::BarcodeFormat_GS1_DATA_MATRIX) return @"GS1_DATA_MATRIX"; + if (format == zxing::BarcodeFormat_GS1_QR_CODE) return @"GS1_QR_CODE"; + if (format == zxing::BarcodeFormat_GS1_128) return @"GS1_128"; + if (format == zxing::BarcodeFormat_GS1_DATA_BAR) return @"GS1_DATA_BAR"; + if (format == zxing::BarcodeFormat_GS1_COMPOSITE) return @"GS1_COMPOSITE"; return @"???"; } @@ -579,6 +602,7 @@ - (UIImage*) getImageFromLuminanceSource:(zxing::LuminanceSource*)luminanceSourc // for debugging //-------------------------------------------------------------------------- - (UIImage*)getImageFromSample:(CMSampleBufferRef)sampleBuffer { + CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); CVPixelBufferLockBaseAddress(imageBuffer, 0); @@ -593,6 +617,7 @@ - (UIImage*)getImageFromSample:(CMSampleBufferRef)sampleBuffer { baseAddress = newBaseAddress; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + CGContextRef context = CGBitmapContextCreate( baseAddress, width, height, 8, bytesPerRow, @@ -824,7 +849,8 @@ - (UIView*)buildOverlayView { #define RETICLE_SIZE 500.0f #define RETICLE_WIDTH 10.0f #define RETICLE_OFFSET 60.0f -#define RETICLE_ALPHA 0.4f +#define RETICLE_ALPHA 1.0f +#define RADIUS 75 //------------------------------------------------------------------------- // builds the green box and red line @@ -833,30 +859,51 @@ - (UIImage*)buildReticleImage { UIImage* result; UIGraphicsBeginImageContext(CGSizeMake(RETICLE_SIZE, RETICLE_SIZE)); CGContextRef context = UIGraphicsGetCurrentContext(); - - if (self.processor.is1D) { - UIColor* color = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:RETICLE_ALPHA]; - CGContextSetStrokeColorWithColor(context, color.CGColor); - CGContextSetLineWidth(context, RETICLE_WIDTH); - CGContextBeginPath(context); - CGFloat lineOffset = RETICLE_OFFSET+(0.5*RETICLE_WIDTH); - CGContextMoveToPoint(context, lineOffset, RETICLE_SIZE/2); - CGContextAddLineToPoint(context, RETICLE_SIZE-lineOffset, 0.5*RETICLE_SIZE); - CGContextStrokePath(context); - } + + // Cross line +// if (self.processor.is1D) { +// UIColor* color = [UIColor colorWithRed:0 green:0.55 blue:0.72 alpha:RETICLE_ALPHA]; +// CGContextSetStrokeColorWithColor(context, color.CGColor); +// CGContextSetLineWidth(context, RETICLE_WIDTH); +// CGContextBeginPath(context); +// CGFloat lineOffset = RETICLE_OFFSET+(0.5*RETICLE_WIDTH); +// CGContextMoveToPoint(context, lineOffset, RETICLE_SIZE/2); +// CGContextAddLineToPoint(context, RETICLE_SIZE-lineOffset, 0.5*RETICLE_SIZE); +// CGContextStrokePath(context); +// } if (self.processor.is2D) { - UIColor* color = [UIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:RETICLE_ALPHA]; + UIColor* color = [UIColor colorWithRed:0.0 green:0.55 blue:0.72 alpha:RETICLE_ALPHA]; CGContextSetStrokeColorWithColor(context, color.CGColor); CGContextSetLineWidth(context, RETICLE_WIDTH); - CGContextStrokeRect(context, - CGRectMake( - RETICLE_OFFSET, - RETICLE_OFFSET, - RETICLE_SIZE-2*RETICLE_OFFSET, - RETICLE_SIZE-2*RETICLE_OFFSET - ) - ); + + // No filling + [[UIColor clearColor] setFill]; + + // rechts unten + CGContextMoveToPoint(context, RETICLE_SIZE - 3*RETICLE_OFFSET, RETICLE_SIZE - RETICLE_OFFSET); + //CGContextAddLineToPoint(context, RETICLE_SIZE-RETICLE_OFFSET, RETICLE_SIZE - RETICLE_OFFSET); + CGContextAddArcToPoint(context, RETICLE_SIZE-RETICLE_OFFSET, RETICLE_SIZE - RETICLE_OFFSET, RETICLE_SIZE - RETICLE_OFFSET, RETICLE_OFFSET, RADIUS); + CGContextAddLineToPoint(context, RETICLE_SIZE-RETICLE_OFFSET, RETICLE_SIZE - 3*RETICLE_OFFSET); + CGContextDrawPath(context, kCGPathFillStroke); + + // rechts oben + CGContextMoveToPoint(context, RETICLE_SIZE - RETICLE_OFFSET, 3*RETICLE_OFFSET); + CGContextAddArcToPoint(context, RETICLE_SIZE - RETICLE_OFFSET, RETICLE_OFFSET, RETICLE_OFFSET, RETICLE_OFFSET, RADIUS); + CGContextAddLineToPoint(context, RETICLE_SIZE-3*RETICLE_OFFSET, RETICLE_OFFSET); + CGContextDrawPath(context, kCGPathFillStroke); + + // links oben + CGContextMoveToPoint(context, 3*RETICLE_OFFSET, RETICLE_OFFSET); + CGContextAddArcToPoint(context, RETICLE_OFFSET, RETICLE_OFFSET, RETICLE_OFFSET, 2*RETICLE_OFFSET, RADIUS); + CGContextAddLineToPoint(context, RETICLE_OFFSET, 3*RETICLE_OFFSET); + CGContextDrawPath(context, kCGPathFillStroke); + + // links unten + CGContextMoveToPoint(context, RETICLE_OFFSET, RETICLE_SIZE - 3*RETICLE_OFFSET); + CGContextAddArcToPoint(context, RETICLE_OFFSET, RETICLE_SIZE - RETICLE_OFFSET, 3*RETICLE_OFFSET, RETICLE_SIZE - RETICLE_OFFSET, RADIUS); + CGContextAddLineToPoint(context, 3*RETICLE_OFFSET, RETICLE_SIZE - RETICLE_OFFSET); + CGContextDrawPath(context, kCGPathFillStroke); } result = UIGraphicsGetImageFromCurrentImageContext(); diff --git a/src/ios/zxing-all-in-one.cpp b/src/ios/zxing-all-in-one.cpp index 2e6e5a510..fac5c0525 100644 --- a/src/ios/zxing-all-in-one.cpp +++ b/src/ios/zxing-all-in-one.cpp @@ -35,7 +35,12 @@ const char *barcodeFormatNames[] = { "EAN_13", "CODE_128", "CODE_39", - "ITF" + "ITF", + "GS1_DATA_MATRIX", + "GS1_QR_CODE", + "GS1_128", + "GS1_DATA_BAR", + "GS1_COMPOSITE" }; } @@ -222,6 +227,11 @@ void DecodeHints::addFormat(BarcodeFormat toadd) { case BarcodeFormat_CODE_128: hints |= BARCODEFORMAT_CODE_128_HINT; break; case BarcodeFormat_CODE_39: hints |= BARCODEFORMAT_CODE_39_HINT; break; case BarcodeFormat_ITF: hints |= BARCODEFORMAT_ITF_HINT; break; +// case BarcodeFormat_GS1_DATA_MATRIX: hints |= BarcodeFormat_GS1_DATA_MATRIX; break; +// case BarcodeFormat_GS1_QR_CODE: hints |= BarcodeFormat_GS1_QR_CODE; break; +// case BarcodeFormat_GS1_128: hints |= BarcodeFormat_GS1_128; break; +// case BarcodeFormat_GS1_DATA_BAR: hints |= BarcodeFormat_GS1_DATA_BAR; break; +// case BarcodeFormat_GS1_COMPOSITE: hints |= BarcodeFormat_GS1_COMPOSITE; break; default: throw IllegalArgumentException("Unrecognizd barcode format"); } } @@ -238,6 +248,11 @@ bool DecodeHints::containsFormat(BarcodeFormat tocheck) const { case BarcodeFormat_CODE_128: checkAgainst = BARCODEFORMAT_CODE_128_HINT; break; case BarcodeFormat_CODE_39: checkAgainst = BARCODEFORMAT_CODE_39_HINT; break; case BarcodeFormat_ITF: checkAgainst = BARCODEFORMAT_ITF_HINT; break; +// case BarcodeFormat_GS1_DATA_MATRIX: checkAgainst = BARCODEFORMAT_GS1_DATA_MATRIX_HINT; break; +// case BarcodeFormat_GS1_QR_CODE: checkAgainst = BARCODEFORMAT_GS1_QR_CODE_HINT; break; +// case BarcodeFormat_GS1_128: checkAgainst = BARCODEFORMAT_GS1_128_HINT; break; +// case BarcodeFormat_GS1_DATA_BAR: checkAgainst = BARCODEFORMAT_GS1_DATA_BAR_HINT; break; +// case BarcodeFormat_GS1_COMPOSITE: checkAgainst = BARCODEFORMAT_GS1_COMPOSITE_HINT; break; default: throw IllegalArgumentException("Unrecognizd barcode format"); } return (hints & checkAgainst); @@ -3877,9 +3892,17 @@ Ref DataMatrixReader::decode(Ref image, DecodeHints hints) #ifdef DEBUG cout << "(4) decoded, have decoderResult " << decoderResult.object_ << "\n" << flush; #endif - - Ref result( - new Result(decoderResult->getText(), decoderResult->getRawBytes(), points, BarcodeFormat_DATA_MATRIX)); + + Ref result; + result = new Result(decoderResult->getText(), decoderResult->getRawBytes(), points, BarcodeFormat_DATA_MATRIX); + + // Detect GS1 Codes + switch (decoderResult->getRawBytes()[0]) { + case 232: + result = new Result(decoderResult->getText(), decoderResult->getRawBytes(), points, BarcodeFormat_GS1_DATA_MATRIX); + break; + } + #ifdef DEBUG cout << "(5) created result " << result.object_ << ", returning\n" << flush; #endif @@ -4783,7 +4806,7 @@ void DecodedBitStreamParser::decodeC40Segment(Ref bits, ostringstream result << C40_SHIFT2_SET_CHARS[cValue]; } } else if (cValue == 27) { // FNC1 - result << ((char) 29); // translate as ASCII 29 + result << ((char) 29); // translate as ASCII 29 } else if (cValue == 30) { // Upper Shift upperShift = true; } else { diff --git a/src/ios/zxing-all-in-one.h b/src/ios/zxing-all-in-one.h index 2718ca9d8..39517d19f 100644 --- a/src/ios/zxing-all-in-one.h +++ b/src/ios/zxing-all-in-one.h @@ -1743,9 +1743,14 @@ namespace zxing { BarcodeFormat_EAN_13, BarcodeFormat_CODE_128, BarcodeFormat_CODE_39, - BarcodeFormat_ITF + BarcodeFormat_ITF, + BarcodeFormat_GS1_DATA_MATRIX, + BarcodeFormat_GS1_QR_CODE, + BarcodeFormat_GS1_128, + BarcodeFormat_GS1_DATA_BAR, + BarcodeFormat_GS1_COMPOSITE } BarcodeFormat; - + /* if you update the enum, please update the name in BarcodeFormat.cpp */ extern const char *barcodeFormatNames[]; } @@ -1903,9 +1908,14 @@ class DecodeHints { static const DecodeHintType BARCODEFORMAT_CODE_128_HINT = 1 << BarcodeFormat_CODE_128; static const DecodeHintType BARCODEFORMAT_CODE_39_HINT = 1 << BarcodeFormat_CODE_39; static const DecodeHintType BARCODEFORMAT_ITF_HINT = 1 << BarcodeFormat_ITF; +// static const DecodeHintType BARCODEFORMAT_GS1_DATA_MATRIX_HINT = 1 << BarcodeFormat_GS1_DATA_MATRIX; +// static const DecodeHintType BARCODEFORMAT_GS1_QR_CODE_HINT = 1 << BarcodeFormat_GS1_QR_CODE; +// static const DecodeHintType BARCODEFORMAT_GS1_128_HINT = 1 << BarcodeFormat_GS1_128; +// static const DecodeHintType BARCODEFORMAT_GS1_DATA_BAR_HINT = 1 << BarcodeFormat_GS1_DATA_BAR; +// static const DecodeHintType BARCODEFORMAT_GS1_COMPOSITE_HINT = 1 << BarcodeFormat_GS1_COMPOSITE; static const DecodeHintType CHARACTER_SET = 1 << 30; static const DecodeHintType TRYHARDER_HINT = 1 << 31; - + static const DecodeHints PRODUCT_HINT; static const DecodeHints ONED_HINT; static const DecodeHints DEFAULT_HINT; diff --git a/www/barcodescanner.js b/www/barcodescanner.js index a2a431d2a..4678f4562 100644 --- a/www/barcodescanner.js +++ b/www/barcodescanner.js @@ -70,7 +70,7 @@ * } * @param {Function} errorCallback */ - BarcodeScanner.prototype.scan = function (successCallback, errorCallback) { + BarcodeScanner.prototype.scan = function (successCallback, errorCallback) { if (errorCallback == null) { errorCallback = function () { };