Генерация QR-кода iOS 7 Core Image слишком размыта

вот мой код для генерации изображения 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];
}

Результат слишком размытый. Можно ли установить размер сгенерированного кода QR?

17 голосов | спросил OMGPOP 13 MarpmThu, 13 Mar 2014 14:01:10 +04002014-03-13T14:01:10+04:0002 2014, 14:01:10

8 ответов


0

Я собирался начать щедрость на этот вопрос, но я нашел ответ.

Вам нужен фильтр масштаба. Чтобы добиться этого с CoreImage, вам нужно сделать что-то вроде этого:

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

ОТ ЭТОГО ТАК ОТВЕТА: https://stackoverflow.com/a/16316701/2859764

ответил Akshit Zaveri 21 MarpmFri, 21 Mar 2014 15:12:19 +04002014-03-21T15:12:19+04:0003 2014, 15:12:19
0

Этот метод будет использовать CoreImage для генерации QR-кода в виде CIImage. К сожалению, нет простого способа отключить интерполяцию, поэтому масштабирование изображения создаст размытый код. Обходной путь должен создать временный CGImageRef с битами и нарисовать его в битовой карте полутонового изображения CGContextRef.

Протестировано на OSX, но должно работать на iOS как написано.

- (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;
}
ответил Dan Waylonis 8 Mayam14 2014, 05:30:44
0

Я столкнулся с той же проблемой, основанной на этом. coreimage-filters" rel =" noreferrer "title =" tutorial "> tutorial Вот как я это исправил:

-(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;
}
ответил cromanelli 10 J0000006Europe/Moscow 2014, 14:07:38
0

Самое простое решение - добавить следующее к вашему изображению:

imgViewQR.layer.magnificationFilter = kCAFilterNearest

Это автоматически увеличит масштаб созданного вами изображения QR-кода до размера изображения, используя nearest, что приведет к четкому пиксельному изображению. Обычно это не то, что нужно при изменении размера значков /фотографий, но идеально подходит для QR-кодов

 введите описание изображения здесь

(похоже, он не работает на симуляторе, но отлично работает на реальном устройстве

ответил Lope 7 J0000006Europe/Moscow 2018, 12:13:18
0

Мне пришлось адаптировать ответ @ Cromanelli для достижения идеальной четкости:

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
}
ответил Benoît Caron 20 Mayam16 2016, 10:30:39
0

Перепишите ответ @ Benoît Caron в 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
}
ответил Bill Chan 11 PMpTue, 11 Apr 2017 12:11:40 +030011Tuesday 2017, 12:11:40
0

Может, тебе стоит попробовать это? Здесь - быстрый учебник.

+ (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];
}
ответил charles 24 FebruaryEurope/MoscowbFri, 24 Feb 2017 05:52:16 +0300000000amFri, 24 Feb 2017 05:52:16 +030017 2017, 05:52:16
0

Чтобы исправить размытие в QR-коде, созданном с помощью CIFilter, выполните следующие действия. Основная идея масштабирования изображения QR-кода без размытия - изменить его свойство transform. Но, поскольку невозможно масштабировать изображение и одновременно добавлять его в представление изображения, мы просто создадим еще один CIImage, который будет увеличен, а затем назначим его представлению изображения.

Цель C:

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

Это помогло мне решить размытые взгляды в QR-коде.

ответил Abilash Balasubramanian 12 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 12 Sep 2017 09:40:36 +0300 2017, 09:40:36

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132