【问题标题】:CIQRCodeGenerator Providing Inconsistent ResultsCIQRCodeGenerator 提供不一致的结果
【发布时间】:2015-12-27 16:44:21
【问题描述】:

我在使用CIQRCodeGenerator创建二维码时遇到问题:一开始生成二维码时很清晰,但是当我再次运行该函数时,使用相同的输入,二维码变得模糊:

初始运行(更清晰):

第二次运行(更模糊):

以下函数首先在viewWillAppear 中调用,随后在用户点击按钮后触发。

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
}

此处提供了说明问题的示例项目:http://jakeserver.com/Uploads/Apps/QR_Test.zip

在使用相同输入第二次运行该函数后 UIImage 变得模糊的原因是什么?

编辑 - 添加更多信息

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);
}

【问题讨论】:

  • In viewDidLoad qrCode.frame.size 可能是不正确的大小。也许将其移至viewDidLayoutSubviews?另外,我认为您应该在viewWillLayoutSubviews 中致电super
  • @AaronBrager 感谢您的所有帮助。我认为将调用移入 didLayout 方法可以在这种情况下修复它。我还有一个更快速的问题:是否有可能让它比现在更清晰?即使是 2 级,它仍然显得有些模糊。
  • @AaronBrager 我找到了后续问题的答案,我必须将比例线中的宽度和高度值加倍。再次感谢您的所有帮助。
  • 顺便说一句,你不需要qrCodeWidth.constant = self.view.frame.width * 0.8——你可以用乘数创建一个“等宽”约束
  • @AaronBrager 内存/处理器效率更高吗?

标签: ios swift uiimageview uiimage core-image


【解决方案1】:

我不确定为什么运行之间的模糊度会发生变化(可能是内部实现细节),但在 Objective-C 代码中,我通过制作 QR 码然后手动将图像写入更大尺寸的位图上下文来解决这个问题。

我尝试将该代码移植到 Swift 并想出了这个:

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
}

这适用于您的用例吗?

顺便说一句,我不认为这会导致您的问题,但您没有打开 datadataUsingEncoding(_:) 返回 NSData? 而不是 NSData)。

【讨论】:

  • 我也不确定CGImageAlphaInfo.NoneCGImageAlphaInfo.NoneSkipFirstCGImageAlphaInfo.NoneSkipLast 是否最适合这里。
  • 感谢您的回答。现在,似乎发生了相反的问题:图像开始模糊,然后在点击按钮时变得更清晰。任何想法为什么会发生这种情况?
  • @JakeChasan 我没有想到。可能与您的视图/视图控制器设置有关,而不是您的 CIFilter 实现?您可以发布您的viewWillAppear 和按钮点击代码吗?
  • 我已经添加了 viewDidLoad、viewWillLayoutSubviews 和按钮点击方法。
猜你喜欢
  • 2014-03-21
  • 1970-01-01
  • 1970-01-01
  • 2017-08-01
  • 1970-01-01
  • 2014-02-03
  • 1970-01-01
  • 2014-09-21
  • 1970-01-01
相关资源
最近更新 更多