CIQRCodeGenerator 提供不一致的结果
CIQRCodeGenerator Providing Inconsistent Results
我在使用 CIQRCodeGenerator
创建 QR 码时遇到问题:当我一开始生成代码时,它很清晰,但是当我再次 运行 使用相同的输入功能时,二维码变得模糊:
初始运行(更清晰):
第二个 运行(更模糊):
以下函数首先在 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);
}
我不确定为什么运行之间的模糊度会发生变化(可能是内部实现细节),但在 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
}
这对您的用例有用吗?
顺便说一句,我不认为这导致了你的问题,但你没有展开 data
(dataUsingEncoding(_:)
returns NSData?
而不是 NSData
).
我在使用 CIQRCodeGenerator
创建 QR 码时遇到问题:当我一开始生成代码时,它很清晰,但是当我再次 运行 使用相同的输入功能时,二维码变得模糊:
初始运行(更清晰):
第二个 运行(更模糊):
以下函数首先在 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);
}
我不确定为什么运行之间的模糊度会发生变化(可能是内部实现细节),但在 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
}
这对您的用例有用吗?
顺便说一句,我不认为这导致了你的问题,但你没有展开 data
(dataUsingEncoding(_:)
returns NSData?
而不是 NSData
).