From Ivory Tortoise, 2 Months ago, written in Text.
Embed
  1.  
  2. import UIKit
  3.  
  4. extension Notification.Name {
  5.     /** Emitted for product codes such as UPC/EAN, QR, or Code 128. 'code' key of userInfo dictionary contains a String representation of the code. */
  6.     static let ScannedProductCode = Notification.Name("com.ailatech.ScannedProductCode")
  7.     /** Emitted for driver's license PDF417 codes. 'code' key of userInfo dictionary contains a String representation of the code. */
  8.     static let ScannedIDCard = Notification.Name("com.ailatech.ScannedIDCard")
  9.     /** Emitted when an ID card image is captured. 'image' key of userInfo dictionary contains a UIImage. */
  10.     static let CapturedIDImage = Notification.Name("com.ailatech.CapturedIDImage")
  11. }
  12.  
  13. @UIApplicationMain
  14. class AppDelegate: UIResponder, UIApplicationDelegate {
  15.     var window: UIWindow?
  16.     var config: PadlocScanConfiguration!
  17.  
  18.     /** Set this property to enable or disable ID card detection. Card detection requires an Interactive Kiosk with a card tray accessory. When enabled, a card image will be captured automatically when the user places a card in the tray. Disabled by default. */
  19.     var cardDetection: Bool {
  20.         get {
  21.             return config.cardDetectionMode == PadlocScanCardDetectionModeOn
  22.         }
  23.         set {
  24.             config.cardDetectionMode = newValue ? PadlocScanCardDetectionModeOn : PadlocScanCardDetectionModeOff
  25.             updateScanningMode()
  26.         }
  27.     }
  28.  
  29.     func updateScanningMode() {
  30.         PadlocScan_SetConfiguration(config)
  31.         switch PadlocScan_GetHardwareClass() {
  32.         case PadlocScanHardwareClassKiosk:
  33.             NSLog("Current Aila device: Interactive Kiosk (camera mirroring enabled)")
  34.             SetPadlocScanMirroring(true)
  35.             // Scanning must be restarted explicitly if hardware class was previously Mobile
  36.             PadlocScan_Start()
  37.         case PadlocScanHardwareClassMobile:
  38.             NSLog("Current Aila device: Mobile Imager (camera mirroring enabled)")
  39.             SetPadlocScanMirroring(true)
  40.             // Scanning is controlled by hardware buttons, so it should be stopped if hardware class was previously Kiosk
  41.             PadlocScan_Stop()
  42.         default:
  43.             NSLog("Current Aila device: none (camera mirroring disabled)")
  44.             SetPadlocScanMirroring(false)
  45.             // PadlocScan functions in Kiosk mode if no device is connected. Standalone scanning is suitable only for development and testing purposes.
  46.             PadlocScan_Start()
  47.         }
  48.     }
  49.  
  50.     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  51.         UIApplication.shared.isIdleTimerDisabled = true
  52.  
  53.         //DisableStandaloneScanLimit()
  54.         config = PadlocScanConfiguration()
  55.         config.enabledCodes = PadlocScanCodeType(PadlocScanCodeTypeUPCEAN.rawValue | PadlocScanCodeTypeQR.rawValue | PadlocScanCodeType128.rawValue | PadlocScanCodeTypePDF417.rawValue)
  56.         config.cardDetectionMode = PadlocScanCardDetectionModeOff
  57.         config.scanCallback = { (type: PadlocScanCodeType, data: String!) in
  58.             DispatchQueue.main.async {
  59.                 NSLog("Scanned barcode: %@", data)
  60.                 let name: Notification.Name
  61.                 switch type {
  62.                 case PadlocScanCodeTypePDF417:
  63.                     name = Notification.Name.ScannedIDCard
  64.                 default:
  65.                     name = Notification.Name.ScannedProductCode
  66.                 }
  67.                 NotificationCenter.default.post(name: name, object: nil, userInfo: ["code": data])
  68.             }
  69.         }
  70.         NotificationCenter.default.addObserver(forName: Notification.Name.PadlocScanHardwareChanged, object: nil, queue: nil) { [weak self] notif in
  71.             DispatchQueue.main.async {
  72.                 self!.updateScanningMode()
  73.             }
  74.         }
  75.         NotificationCenter.default.addObserver(forName: Notification.Name.PadlocScanCardDetected, object: nil, queue: nil) { [weak self] notif in
  76.             DispatchQueue.main.async {
  77.                 self!.captureImage()
  78.             }
  79.         }
  80.         PadlocScan_Init()
  81.         updateScanningMode()
  82.         return true
  83.     }
  84.  
  85.     func captureImage() {
  86.         PadlocScan_CaptureImage { (image: UIImage!, error: Error?) in
  87.             DispatchQueue.main.async {
  88.                 if let e = error {
  89.                     NSLog("Error occurred while capturing image: %@", e as NSError);
  90.                 }
  91.                 else {
  92.                     NotificationCenter.default.post(name: Notification.Name.CapturedIDImage, object: nil, userInfo: ["image": image])
  93.                 }
  94.             }
  95.         }
  96.     }
  97.  
  98.  
  99. }
  100.  
  101.  
  102.  
  103.  
  104.  
  105. //PadlocScanHooks.h
  106.  
  107. /** Control PadlocScan camera mirroring. When the iOS device is installed in an Aila case, a mirror inverts the camera view. Certain barcode symbologies cannot be scanned without compensating for the inversion. If the iOS device is NOT installed in a case, compensation must NOT be done. */
  108. void SetPadlocScanMirroring(BOOL mirror);
  109.  
  110. /** Generate a QR image that encodes a list of product codes. The content of this QR code can then be parsed by ParseTransferQR(). For `viewSize`, pass the dimensions of the UIImageView within which the QR code will be displayed; the QR code will be scaled to the largest size that will fit within `viewSize` without blurring. The image view's contentMode should be set to UIViewContentModeCenter or any other non-scaling mode. */
  111. UIImage *_Nonnull GenerateTransferQR(NSArray<NSString *> *_Nonnull codes, CGSize viewSize);
  112.  
  113. /** If `qrContent` represents a transfer QR code, return the list of product codes to be transferred. Otherwise, return nil. */
  114. NSArray<NSString *> *_Nullable ParseTransferQR(NSString *_Nonnull qrContent);
  115.  
  116.  
  117.  
  118. //PadlocScanHooks.m
  119.  
  120.  
  121. #import <PadlocScan/PadlocScan.h>
  122. #import "PadlocScanHooks.h"
  123. #import <CoreImage/CoreImage.h>
  124. #import <UIKit/UIKit.h>
  125.  
  126. void SetPadlocScanMirroring(BOOL mirror) {
  127.     id hook = PadlocScan_GetInternalHook();
  128.     if (!hook) return;
  129.     id config = [hook valueForKey:@"config"];
  130.     if (!config) return;
  131.     config[@"scan.mirror"] = @(mirror);
  132. }
  133.  
  134. static NSString *const transferQRPrefix = @"AILACART:";
  135.  
  136. UIImage *_Nonnull GenerateTransferQR(NSArray<NSString *> *codes, CGSize viewSize) {
  137.     // Ensure data is long enough that the alignment marker will appear in the QR code. QR codes without an alignment marker cannot be scanned at oblique angles.
  138.     NSMutableData *data = nil;
  139.     int npad = 0;
  140.     do {
  141.         data = [NSMutableData data];
  142.         [data appendData:[transferQRPrefix dataUsingEncoding:NSUTF8StringEncoding]];
  143.         NSDictionary *body = @{@"_": [NSString stringWithFormat:@"%*s", npad, ""], @"items": codes};
  144.         [data appendData:[NSJSONSerialization dataWithJSONObject:body options:0 error:nil] ?: [NSData data]];
  145.         ++npad;
  146.     } while (data.length < 16);
  147.  
  148.     CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
  149.     [filter setDefaults];
  150.     [filter setValue:data forKey:@"inputMessage"];
  151.  
  152.     CIImage *rawim = filter.outputImage;
  153.     CGFloat scale = MAX(1.0, floor(MIN(viewSize.width / rawim.extent.size.width, viewSize.height / rawim.extent.size.height)));
  154.     CIImage *sclim = [rawim imageByApplyingTransform:CGAffineTransformMakeScale(scale, scale)];
  155.     return [UIImage imageWithCGImage:[[CIContext contextWithOptions:nil] createCGImage:sclim fromRect:sclim.extent]];
  156. }
  157.  
  158. NSArray<NSString *> *_Nullable ParseTransferQR(NSString *_Nonnull qrContent) {
  159.     if (![qrContent hasPrefix:transferQRPrefix]) {return nil;}
  160.     id body = [NSJSONSerialization JSONObjectWithData:[[qrContent substringFromIndex:transferQRPrefix.length] dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
  161.     if (!body) {return nil;}
  162.     if (!([body isKindOfClass:[NSDictionary class]] && [body[@"items"] isKindOfClass:[NSArray class]])) {return nil;}
  163.     for (id x in body[@"items"]) {
  164.         if (![x isKindOfClass:[NSString class]]) {return nil;}
  165.     }
  166.     return body[@"items"];
  167. }
  168.  
  169.  
  170.  
  171.  
  172.  

Replies to Untitled rss

Title Name Language When
Re: Untitled Red Peafowl text 2 Months ago.