简体   繁体   中英

CIQRCodeGenerator Providing Inconsistent Results

I am experiencing a problem using CIQRCodeGenerator to create a QR code: when I generate the code at first, it is crisp, but when I run the function again, with the same input, the QR code becomes blurry:

Initial Run (more clear):

初始功能运行

Second Run (more blurry):

第二功能运行

The following function is first called in viewWillAppear and subsequently triggered after the user taps a button.

func generateQRCodeFromString(string: String) -> UIImage? {
    let data = string.dataUsingEncoding(NSISOLatin1StringEncoding)

    if let filter = CIFilter(name: "CIQRCodeGenerator") {
        filter.setValue(data, forKey: "inputMessage")
        filter.setValue("H", forKey: "inputCorrectionLevel")
        let transform = CGAffineTransformMakeScale(10, 10)

        if let output = filter.outputImage?.imageByApplyingTransform(transform) {
            return UIImage(CIImage: output)
        }
    }

    return nil
}

A sample project illustrating the problem is available here: http://jakeserver.com/Uploads/Apps/QR_Test.zip

Is there a reason why the UIImage becomes blurry after the function is run a second time with the same input?

EDIT - Added More Information

override func viewDidLoad() {
    super.viewDidLoad()
    qrCode.image = generateQRCodeFromString("test", size: qrCode.frame.size);
}

override func viewWillLayoutSubviews() {
    qrCodeWidth.constant = self.view.frame.width * 0.8;
}
@IBAction func buttonTapped(sender: AnyObject) {
    qrCode.image = generateQRCodeFromString("test", size: qrCode.frame.size);
}

I'm not sure why the blurriness changes between runs (maybe an internal implementation detail), but in Objective-C code I worked around this by making the QR code and then manually writing the image into a larger sized bitmap context.

I took a stab at porting that code to Swift and came up with this:

func generateQRCodeFromString(string: String, size: CGSize) -> UIImage? {
    guard let data = string.dataUsingEncoding(NSISOLatin1StringEncoding),
        let filter = CIFilter(name: "CIQRCodeGenerator") else { return nil }

    filter.setDefaults()
    filter.setValue(data, forKey: "inputMessage")
    filter.setValue("H", forKey: "inputCorrectionLevel")

    guard let image = filter.outputImage else { return nil }

    let extent = CGRectIntegral(image.extent)
    let scale = min(size.width / extent.width, size.height / extent.height);

    let (height, width) = (extent.height * scale, extent.width * scale)
    let colorSpace = CGColorSpaceCreateDeviceGray()
    let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.None.rawValue)

    guard let bitmapContext = CGBitmapContextCreate(nil, Int(width), Int(height), 8, 0, colorSpace, bitmapInfo.rawValue) else { return nil }

    CGContextSetInterpolationQuality(bitmapContext, CGInterpolationQuality.None)
    CGContextScaleCTM(bitmapContext, CGFloat(scale), CGFloat(scale))
    CGContextDrawImage(bitmapContext, extent, CIContext().createCGImage(image, fromRect: extent))

    if let scaledImage = CGBitmapContextCreateImage(bitmapContext) {
        return UIImage(CGImage: scaledImage)
//        You might need to use this instead:
//        return UIImage(CGImage: <#T##CGImage#>, scale: <#T##CGFloat#>, orientation: <#T##UIImageOrientation#>)

    }

    return nil
}

Will that work for your use case?

BTW, I don't think this caused your issue, but you weren't unwrapping data ( dataUsingEncoding(_:) returns NSData? not NSData ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM