Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/zxing-cpp/wrappers/ios/Sources/Wrapper/Reader/ZXIBarcodeReader.mm @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 // Copyright 2022 KURZ Digital Solutions GmbH | |
| 2 // | |
| 3 // SPDX-License-Identifier: Apache-2.0 | |
| 4 | |
| 5 #import "ZXIBarcodeReader.h" | |
| 6 #import "ReadBarcode.h" | |
| 7 #import "ImageView.h" | |
| 8 #import "Barcode.h" | |
| 9 #import "GTIN.h" | |
| 10 #import "ZXIFormatHelper.h" | |
| 11 #import "ZXIPosition+Helper.h" | |
| 12 #import "ZXIErrors.h" | |
| 13 | |
| 14 using namespace ZXing; | |
| 15 | |
| 16 NSString *stringToNSString(const std::string &text) { | |
| 17 return [[NSString alloc]initWithBytes:text.data() length:text.size() encoding:NSUTF8StringEncoding]; | |
| 18 } | |
| 19 | |
| 20 ZXIGTIN *getGTIN(const Result &result) { | |
| 21 try { | |
| 22 auto country = GTIN::LookupCountryIdentifier(result.text(TextMode::Plain), result.format()); | |
| 23 auto addOn = GTIN::EanAddOn(result); | |
| 24 return country.empty() | |
| 25 ? nullptr | |
| 26 : [[ZXIGTIN alloc]initWithCountry:stringToNSString(country) | |
| 27 addOn:stringToNSString(addOn) | |
| 28 price:stringToNSString(GTIN::Price(addOn)) | |
| 29 issueNumber:stringToNSString(GTIN::IssueNr(addOn))]; | |
| 30 } catch (std::exception e) { | |
| 31 // Because invalid GTIN data can lead to exceptions, in which case | |
| 32 // we don't want to discard the whole result. | |
| 33 return nullptr; | |
| 34 } | |
| 35 } | |
| 36 | |
| 37 @interface ZXIReaderOptions() | |
| 38 @property(nonatomic) ZXing::ReaderOptions cppOpts; | |
| 39 @end | |
| 40 | |
| 41 @interface ZXIBarcodeReader() | |
| 42 @property (nonatomic, strong) CIContext* ciContext; | |
| 43 @end | |
| 44 | |
| 45 @implementation ZXIBarcodeReader | |
| 46 | |
| 47 - (instancetype)init { | |
| 48 return [self initWithOptions: [[ZXIReaderOptions alloc] init]]; | |
| 49 } | |
| 50 | |
| 51 - (instancetype)initWithOptions:(ZXIReaderOptions*)options{ | |
| 52 self = [super init]; | |
| 53 self.ciContext = [[CIContext alloc] initWithOptions:@{kCIContextWorkingColorSpace: [NSNull new]}]; | |
| 54 self.options = options; | |
| 55 return self; | |
| 56 } | |
| 57 | |
| 58 - (NSArray<ZXIResult *> *)readCVPixelBuffer:(nonnull CVPixelBufferRef)pixelBuffer | |
| 59 error:(NSError *__autoreleasing _Nullable *)error { | |
| 60 OSType pixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer); | |
| 61 | |
| 62 // We tried to work with all luminance based formats listed in kCVPixelFormatType | |
| 63 // but only the following ones seem to be supported on iOS. | |
| 64 switch (pixelFormat) { | |
| 65 case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: | |
| 66 case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange: | |
| 67 NSInteger cols = CVPixelBufferGetWidth(pixelBuffer); | |
| 68 NSInteger rows = CVPixelBufferGetHeight(pixelBuffer); | |
| 69 NSInteger bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0); | |
| 70 CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); | |
| 71 const uint8_t * bytes = static_cast<const uint8_t *>(CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0)); | |
| 72 ImageView imageView = ImageView( | |
| 73 static_cast<const uint8_t *>(bytes), | |
| 74 static_cast<int>(cols), | |
| 75 static_cast<int>(rows), | |
| 76 ImageFormat::Lum, | |
| 77 static_cast<int>(bytesPerRow), | |
| 78 0); | |
| 79 NSArray* results = [self readImageView:imageView error:error]; | |
| 80 CVPixelBufferUnlockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); | |
| 81 return results; | |
| 82 } | |
| 83 | |
| 84 // If given pixel format is not a supported type with a luminance channel we just use the | |
| 85 // default method | |
| 86 return [self readCIImage:[[CIImage alloc] initWithCVImageBuffer:pixelBuffer] error:error]; | |
| 87 } | |
| 88 | |
| 89 - (NSArray<ZXIResult *> *)readCIImage:(nonnull CIImage *)image | |
| 90 error:(NSError *__autoreleasing _Nullable *)error { | |
| 91 CGImageRef cgImage = [self.ciContext createCGImage:image fromRect:image.extent]; | |
| 92 auto results = [self readCGImage:cgImage error:error]; | |
| 93 CGImageRelease(cgImage); | |
| 94 return results; | |
| 95 } | |
| 96 | |
| 97 - (NSArray<ZXIResult *> *)readCGImage:(nonnull CGImageRef)image | |
| 98 error:(NSError *__autoreleasing _Nullable *)error { | |
| 99 CGFloat cols = CGImageGetWidth(image); | |
| 100 CGFloat rows = CGImageGetHeight(image); | |
| 101 NSMutableData *data = [NSMutableData dataWithLength: cols * rows]; | |
| 102 | |
| 103 CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); | |
| 104 CGContextRef contextRef = CGBitmapContextCreate(data.mutableBytes,// Pointer to backing data | |
| 105 cols, // Width of bitmap | |
| 106 rows, // Height of bitmap | |
| 107 8, // Bits per component | |
| 108 cols, // Bytes per row | |
| 109 colorSpace, // Colorspace | |
| 110 kCGBitmapByteOrderDefault); // Bitmap info flags | |
| 111 CGColorSpaceRelease(colorSpace); | |
| 112 CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image); | |
| 113 CGContextRelease(contextRef); | |
| 114 | |
| 115 ImageView imageView = ImageView( | |
| 116 static_cast<const uint8_t *>(data.bytes), | |
| 117 static_cast<int>(cols), | |
| 118 static_cast<int>(rows), | |
| 119 ImageFormat::Lum); | |
| 120 return [self readImageView:imageView error:error]; | |
| 121 } | |
| 122 | |
| 123 - (NSArray<ZXIResult*> *)readImageView:(ImageView)imageView | |
| 124 error:(NSError *__autoreleasing _Nullable *)error { | |
| 125 try { | |
| 126 Barcodes results = ReadBarcodes(imageView, self.options.cppOpts); | |
| 127 NSMutableArray* zxiResults = [NSMutableArray array]; | |
| 128 for (auto result: results) { | |
| 129 [zxiResults addObject: | |
| 130 [[ZXIResult alloc] init:stringToNSString(result.text()) | |
| 131 format:ZXIFormatFromBarcodeFormat(result.format()) | |
| 132 bytes:[[NSData alloc] initWithBytes:result.bytes().data() length:result.bytes().size()] | |
| 133 position:[[ZXIPosition alloc]initWithPosition: result.position()] | |
| 134 orientation:result.orientation() | |
| 135 ecLevel:stringToNSString(result.ecLevel()) | |
| 136 symbologyIdentifier:stringToNSString(result.symbologyIdentifier()) | |
| 137 sequenceSize:result.sequenceSize() | |
| 138 sequenceIndex:result.sequenceIndex() | |
| 139 sequenceId:stringToNSString(result.sequenceId()) | |
| 140 readerInit:result.readerInit() | |
| 141 lineCount:result.lineCount() | |
| 142 gtin:getGTIN(result)] | |
| 143 ]; | |
| 144 } | |
| 145 return zxiResults; | |
| 146 } catch(std::exception &e) { | |
| 147 SetNSError(error, ZXIReaderError, e.what()); | |
| 148 return nil; | |
| 149 } catch (...) { | |
| 150 SetNSError(error, ZXIReaderError, "An unknown error occurred"); | |
| 151 return nil; | |
| 152 } | |
| 153 } | |
| 154 | |
| 155 @end |
