personalizados - iOS 7 Core Image Código QR generación demasiado borrosa
escanear codigo qr iphone (8)
Aquí está mi código para generar la imagen QRCode
+ (UIImage *)generateQRCodeWithString:(NSString *)string {
NSData *stringData = [string dataUsingEncoding:NSUTF8StringEncoding];
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
[filter setValue:stringData forKey:@"inputMessage"];
[filter setValue:@"M" forKey:@"inputCorrectionLevel"];
return [UIImage imageWithCIImage:filter.outputImage];
}
El resultado es demasiado borroso. ¿Es posible establecer el tamaño del código qr generado?
Estaba a punto de empezar con generosidad en esta pregunta, pero encontré la respuesta.
Lo que necesitas es un filtro de escala. Para lograr esto con CoreImage, necesitas hacer algo como esto:
CIImage *input = [CIImage imageWithCGImage: ImageView.Image.CGImage]; // input image is 100 X 100
CGAffineTransform transform = CGAffineTransformMakeScale(5.0f, 5.0f); // Scale by 5 times along both dimensions
CIImage *output = [input imageByApplyingTransform: transform];
// output image is now 500 X 500
DESDE ESTA RESPUESTA: https://.com/a/16316701/2859764
Este método utilizará CoreImage para generar el código QR como un CIImage. Desafortunadamente, no hay una forma sencilla de deshabilitar la interpolación, por lo que escalar la imagen creará un código borroso. La solución es crear CGImageRef temporal con los bits y dibujarlo en un mapa de bits de escala de grises CGContextRef.
Probado en OSX, pero debería funcionar en iOS como está escrito.
- (CGImageRef)createQRImageForString:(NSString *)string size:(CGSize)size {
// Setup the QR filter with our string
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
[filter setDefaults];
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
[filter setValue:data forKey:@"inputMessage"];
CIImage *image = [filter valueForKey:@"outputImage"];
// Calculate the size of the generated image and the scale for the desired image size
CGRect extent = CGRectIntegral(image.extent);
CGFloat scale = MIN(size.width / CGRectGetWidth(extent), size.height / CGRectGetHeight(extent));
// Since CoreImage nicely interpolates, we need to create a bitmap image that we''ll draw into
// a bitmap context at the desired size;
size_t width = CGRectGetWidth(extent) * scale;
size_t height = CGRectGetHeight(extent) * scale;
CGColorSpaceRef cs = CGColorSpaceCreateDeviceGray();
CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, cs, (CGBitmapInfo)kCGImageAlphaNone);
#if TARGET_OS_IPHONE
CIContext *context = [CIContext contextWithOptions:nil];
#else
CIContext *context = [CIContext contextWithCGContext:bitmapRef options:nil];
#endif
CGImageRef bitmapImage = [context createCGImage:image fromRect:extent];
CGContextSetInterpolationQuality(bitmapRef, kCGInterpolationNone);
CGContextScaleCTM(bitmapRef, scale, scale);
CGContextDrawImage(bitmapRef, extent, bitmapImage);
// Create an image with the contents of our bitmap
CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
// Cleanup
CGContextRelease(bitmapRef);
CGImageRelease(bitmapImage);
return scaledImage;
}
La solución más sencilla es agregar lo siguiente a su vista de imagen:
imgViewQR.layer.magnificationFilter = kCAFilterNearest
Esto elevará automáticamente la imagen de su código QR generado al tamaño de la vista de la imagen, lo que se traducirá en una imagen nítida y pixelada. Por lo general, esto no es lo que desea cuando cambia el tamaño de los iconos / fotos, pero es perfecto para los códigos QR
(Parece que no funciona en el simulador, pero funciona muy bien en dispositivos reales
Me encontré con el mismo problema, basado en este tutorial así es como lo solucioné:
-(UIImage *) generateQRCodeWithString:(NSString *)string scale:(CGFloat) scale{
NSData *stringData = [string dataUsingEncoding:NSUTF8StringEncoding ];
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
[filter setValue:stringData forKey:@"inputMessage"];
[filter setValue:@"M" forKey:@"inputCorrectionLevel"];
// Render the image into a CoreGraphics image
CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:[filter outputImage] fromRect:[[filter outputImage] extent]];
//Scale the image usign CoreGraphics
UIGraphicsBeginImageContext(CGSizeMake([[filter outputImage] extent].size.width * scale, [filter outputImage].extent.size.width * scale));
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetInterpolationQuality(context, kCGInterpolationNone);
CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage);
UIImage *preImage = UIGraphicsGetImageFromCurrentImageContext();
//Cleaning up .
UIGraphicsEndImageContext();
CGImageRelease(cgImage);
// Rotate the image
UIImage *qrImage = [UIImage imageWithCGImage:[preImage CGImage]
scale:[preImage scale]
orientation:UIImageOrientationDownMirrored];
return qrImage;
}
Quizás deberías intentar esto. Here hay un tutotial rápido.
+ (UIImage *)generateQRCodeImageBySize:(CGFloat)size andString:(NSString *)string {
CIImage *qrCodeImage = [[CIImage alloc] init];
NSData *stringData = [string dataUsingEncoding:NSISOLatin1StringEncoding allowLossyConversion:NO];
CIFilter *ciFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
[ciFilter setValue:stringData forKey:@"inputMessage"];
[ciFilter setValue:@"Q" forKey:@"inputCorrectionLevel"];
qrCodeImage = ciFilter.outputImage;
CGFloat scaleX = size / qrCodeImage.extent.size.width;
CGFloat scaleY = size / qrCodeImage.extent.size.height;
CIImage *transformedQRImage = [qrCodeImage imageByApplyingTransform:CGAffineTransformMakeScale(scaleX, scaleY)];
return [UIImage imageWithCIImage:transformedQRImage];
}
Reescribe la respuesta de @ Benoît Caron en Swift 3.1:
func convertTextToQRCode(text: String, withSize size: CGSize) -> UIImage {
let data = text.data(using: String.Encoding.isoLatin1, allowLossyConversion: false)
let filter = CIFilter(name: "CIQRCodeGenerator")!
filter.setValue(data, forKey: "inputMessage")
filter.setValue("L", forKey: "inputCorrectionLevel")
let qrcodeCIImage = filter.outputImage!
let cgImage = CIContext(options:nil).createCGImage(qrcodeCIImage, from: qrcodeCIImage.extent)
UIGraphicsBeginImageContext(CGSize(width: size.width * UIScreen.main.scale, height:size.height * UIScreen.main.scale))
let context = UIGraphicsGetCurrentContext()
context!.interpolationQuality = .none
context?.draw(cgImage!, in: CGRect(x: 0.0,y: 0.0,width: context!.boundingBoxOfClipPath.width,height: context!.boundingBoxOfClipPath.height))
let preImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let qrCodeImage = UIImage(cgImage: (preImage?.cgImage!)!, scale: 1.0/UIScreen.main.scale, orientation: .downMirrored)
return qrCodeImage
}
Tuve que adaptar la respuesta de @ cromanelli para lograr una nitidez perfecta:
func convertTextToQRCode(text: String, withSize size: CGSize) -> UIImage {
let data = text.dataUsingEncoding(NSISOLatin1StringEncoding, allowLossyConversion: false)
let filter = CIFilter(name: "CIQRCodeGenerator")!
filter.setValue(data, forKey: "inputMessage")
filter.setValue("L", forKey: "inputCorrectionLevel")
var qrcodeCIImage = filter.outputImage!
let cgImage = CIContext(options:nil).createCGImage(qrcodeCIImage, fromRect: qrcodeCIImage.extent)
UIGraphicsBeginImageContext(CGSizeMake(size.width * UIScreen.mainScreen().scale, size.height * UIScreen.mainScreen().scale))
let context = UIGraphicsGetCurrentContext()
CGContextSetInterpolationQuality(context, .None)
CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage)
let preImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let qrCodeImage = UIImage(CGImage: preImage.CGImage!, scale: 1.0/UIScreen.mainScreen().scale, orientation: .DownMirrored)
return qrCodeImage
}
Para corregir el aspecto borroso en el código QR generado mediante el uso de CIFilter: La idea básica para ampliar la imagen del código QR sin hacerlo borroso es cambiar su propiedad de transformación. Pero, como no es factible escalar la imagen y agregarla al mismo tiempo a la vista de imagen, solo crearemos otro CIImage que se ampliará y luego lo asignaremos a la vista de imagen.
C objetivo:
- (void)createQRForData:(id)qrData forImageView:(UIImageView *)imageView {
NSData *data = [NSJSONSerialization dataWithJSONObject:qrData options:NSJSONWritingPrettyPrinted error:nil];
CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
[qrFilter setValue:data forKey:@"inputMessage"];
[qrFilter setValue:@"Q" forKey: @"inputCorrectionLevel"];
//Scaling the CIFilter image as per the UIImageView frame.
CGFloat scaleX = imageView.frame.size.width / qrFilter.outputImage.extent.size.width;
CGFloat scaleY = imageView.frame.size.height / qrFilter.outputImage.extent.size.height;
CIImage *transformedImage = [qrFilter.outputImage imageByApplyingTransform:CGAffineTransformMakeScale(scaleX, scaleY)];
UIImage *QRImage = [UIImage imageWithCIImage:transformedImage];
imageView.image = QRImage;
}
Esto me ayudó a resolver los looks borrosos en el código QR.