I am trying to scan QR images that user chooses from disk. I found a strange issue where all libraries I tried failed (CIDetector old port of ZXING or ZBAR). I know that there are ways to add white background (e.g. redraw image or using CIFilter) so the image will get scanned.
What is the correct way of scanning QR codes with transparent background (configure CIContext or CIDetector). (the image below fails to scan on iOS and macOS).
https://en.wikipedia.org/wiki/QR_code#/media/File:QR_code_for_mobile_English_Wikipedia.svg

- (void)scanImage:(CIImage *)image
{
NSArray <CIFeature *>*features = [[self QRdetector] featuresInImage:image];
NSLog(@"Number of features found: %lu", [features count]);
}
- (CIDetector *)QRdetector
{
CIContext *context = [CIContext contextWithOptions:@{kCIContextWorkingColorSpace : [NSNull null]}]; //no difference using special options or nil as a context
CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:context options:@{CIDetectorAccuracy : CIDetectorAccuracyHigh, CIDetectorAspectRatio : @(1)}];
return detector;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSURL *URL = [[NSBundle mainBundle] URLForResource:@"transparentqrcode" withExtension:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:[URL path]];
CIImage *ciImage = [CIImage imageWithContentsOfURL:URL];
//CUSTOM CODE TO ADD WHITE BACKGROUND
CIFilter *filter = [CIFilter filterWithName:@"CISourceAtopCompositing"];
[filter setDefaults];
CIColor *whiteColor = [[CIColor alloc] initWithColor:[UIColor whiteColor]];
CIImage *colorImage = [CIImage imageWithColor:whiteColor];
colorImage = [colorImage imageByCroppingToRect:ciImage.extent];
[filter setValue:ciImage forKey:kCIInputImageKey];
[filter setValue:colorImage forKey:kCIInputBackgroundImageKey];
CIImage *newImage = [filter valueForKey:kCIOutputImageKey];
[self scanImage:ciImage];
return YES;
}
As mentioned in the comments, it appears
CIDetectortreats the alpha channel as black. Replacing it with white works --- unless the QRCode itself is white with a transparent background.I haven't done any profiling to see if this would be quicker, but it might be a better option.