Pregunta iOS 7 Core Image QR Code genera demasiado borroso


aquí está mi código para generar una imagen de 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?


15
2018-03-13 10:01


origen


Respuestas:


Estaba a punto de comenzar generosamente con 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://stackoverflow.com/a/16316701/2859764


25
2018-03-21 11:12



Este método usará CoreImage para generar el código QR como un CIImage. Desafortunadamente, no hay una forma simple de desactivar la interpolación, por lo que escalar la imagen creará un código borroso. La solución consiste en crear CGImageRef temporal con los bits y dibujarlo en un mapa de bits en 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;
}

14
2018-05-08 01:30



Me encontré con el mismo problema, basado en esto tutorial así es como lo arreglé:

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

9
2018-06-10 10:07



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
}

3
2018-05-20 07:30



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
}

2
2018-04-11 09:11



La solución más fácil es agregar lo siguiente a su vista de imagen:

imgViewQR.layer.magnificationFilter = kCAFilterNearest

Esto aumentará automáticamente la escala de la imagen del código QR generado al tamaño de la imagen con el uso nearest que da como resultado una imagen nítida y pixelada. Por lo general, esto no es lo que desea al cambiar el tamaño de los iconos / fotos, pero es Perfecto para códigos QR

enter image description here

(No parece funcionar en el simulador, pero funciona muy bien en el dispositivo real


1
2018-06-07 09:13



Quizás deberías probar esto. aquí es 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];
}

0
2018-02-24 02:52



Para corregir el efecto borroso se ve el código QR generado al usar 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 la imagen, crearemos otro CIImage que se ampliará y luego lo asignaremos a la vista de la 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 las miradas borrosas en el código QR.


0
2017-09-12 06:40