iOS 7 Core Image QR-код слишком размытие
вот мой код для генерации изображения 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-кода?
8 ответов
Я собирался начать баунти на этот вопрос, но я нашел ответ.
вам нужен масштабный фильтр. Чтобы достичь этого с помощью 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
этот метод будет использовать 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;
}
я столкнулся с той же проблемой, основываясь на этом учебник вот как я это исправил :
-(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 для достижения идеальной резкости:
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
}
самое простое решение-добавить следующее к вашему представлению изображения:
imgViewQR.layer.magnificationFilter = kCAFilterNearest
это автоматически повысит ваш сгенерированный QR-код изображения до размера imageview с помощью nearest
что приводит к резкому, неровному изображению. Обычно это не то, что вы хотите при изменении размера значков/фотографий, но это идеальный для QR-кодов
(похоже, он не работает на симуляторе, но отлично работает на реальном устройстве
перепишите ответ @ 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
}
Возможно, вам стоит попробовать это. здесь - быстрый tutotial.
+ (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];
}
чтобы исправить размытие выглядит в QR-коде, сгенерированном с помощью CIFilter: основная идея для масштабирования изображения QR-кода, не делая его размытым, заключается в изменении его свойства преобразования. Но, поскольку масштабировать изображение и одновременно добавлять его в представление изображения невозможно, мы просто создадим еще один 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-код.