You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
5.8 KiB
154 lines
5.8 KiB
// |
|
// LCQrcodeUtil.m |
|
// 二维码测试 |
|
// |
|
// Created by 刘通超 on 16/5/5. |
|
// Copyright © 2016年 刘通超. All rights reserved. |
|
// |
|
|
|
#import "LCQRCodeUtil.h" |
|
|
|
@implementation LCQRCodeUtil |
|
|
|
#pragma mark 读取图片二维码 |
|
/** |
|
* 读取图片中二维码信息 |
|
* |
|
* @param image 图片 |
|
* |
|
* @return 二维码内容 |
|
*/ |
|
+(NSString *)readQRCodeFromImage:(UIImage *)image{ |
|
NSData *data = UIImagePNGRepresentation(image); |
|
CIImage *ciimage = [CIImage imageWithData:data]; |
|
if (ciimage) { |
|
CIDetector *qrDetector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:[CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer:@(YES)}] options:@{CIDetectorAccuracy : CIDetectorAccuracyHigh}]; |
|
NSArray *resultArr = [qrDetector featuresInImage:ciimage]; |
|
if (resultArr.count >0) { |
|
CIFeature *feature = resultArr[0]; |
|
CIQRCodeFeature *qrFeature = (CIQRCodeFeature *)feature; |
|
NSString *result = qrFeature.messageString; |
|
|
|
return result; |
|
}else{ |
|
return nil; |
|
} |
|
}else{ |
|
return nil; |
|
} |
|
} |
|
|
|
#pragma mark 生成二维码 |
|
/** |
|
* 生成二维码图片 |
|
* |
|
* @param QRString 二维码内容 |
|
* @param sizeWidth 图片size(正方形) |
|
* @param color 填充色 |
|
* |
|
* @return 二维码图片 |
|
*/ |
|
+(UIImage *)createQRimageString:(NSString *)QRString sizeWidth:(CGFloat)sizeWidth fillColor:(UIColor *)color{ |
|
CIImage *ciimage = [self createQRForString:QRString]; |
|
UIImage *qrcode = [self createNonInterpolatedUIImageFormCIImage:ciimage withSize:sizeWidth]; |
|
if (color) { |
|
CGFloat R=0, G=0, B=0; |
|
|
|
CGColorRef colorRef = [color CGColor]; |
|
long numComponents = CGColorGetNumberOfComponents(colorRef); |
|
|
|
if (numComponents == 4) |
|
{ |
|
const CGFloat *components = CGColorGetComponents(colorRef); |
|
R = components[0]; |
|
G = components[1]; |
|
B = components[2]; |
|
} |
|
|
|
UIImage *customQrcode = [self imageBlackToTransparent:qrcode withRed:R andGreen:G andBlue:B]; |
|
return customQrcode; |
|
} |
|
|
|
return qrcode; |
|
|
|
} |
|
#pragma mark - QRCodeGenerator |
|
+ (CIImage *)createQRForString:(NSString *)qrString { |
|
// Need to convert the string to a UTF-8 encoded NSData object |
|
NSData *stringData = [qrString dataUsingEncoding:NSUTF8StringEncoding]; |
|
// Create the filter |
|
CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"]; |
|
// Set the message content and error-correction level |
|
[qrFilter setValue:stringData forKey:@"inputMessage"]; |
|
[qrFilter setValue:@"M" forKey:@"inputCorrectionLevel"]; |
|
// Send the image back |
|
return qrFilter.outputImage; |
|
} |
|
|
|
|
|
#pragma mark - InterpolatedUIImage |
|
+ (UIImage *)createNonInterpolatedUIImageFormCIImage:(CIImage *)image withSize:(CGFloat) size { |
|
CGRect extent = CGRectIntegral(image.extent); |
|
CGFloat scale = MIN(size/CGRectGetWidth(extent), size/CGRectGetHeight(extent)); |
|
// 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); |
|
CIContext *context = [CIContext contextWithOptions:nil]; |
|
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 [UIImage imageWithCGImage:scaledImage]; |
|
} |
|
|
|
#pragma mark - imageToTransparent |
|
void ProviderReleaseData (void *info, const void *data, size_t size){ |
|
free((void*)data); |
|
} |
|
+ (UIImage*)imageBlackToTransparent:(UIImage*)image withRed:(CGFloat)red andGreen:(CGFloat)green andBlue:(CGFloat)blue{ |
|
const int imageWidth = image.size.width; |
|
const int imageHeight = image.size.height; |
|
size_t bytesPerRow = imageWidth * 4; |
|
uint32_t* rgbImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight); |
|
// create context |
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); |
|
CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace, |
|
kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast); |
|
CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), image.CGImage); |
|
// traverse pixe |
|
int pixelNum = imageWidth * imageHeight; |
|
uint32_t* pCurPtr = rgbImageBuf; |
|
for (int i = 0; i < pixelNum; i++, pCurPtr++){ |
|
if ((*pCurPtr & 0xFFFFFF00) < 0x99999900){ |
|
// change color |
|
uint8_t* ptr = (uint8_t*)pCurPtr; |
|
ptr[3] = red; //0~255 |
|
ptr[2] = green; |
|
ptr[1] = blue; |
|
}else{ |
|
uint8_t* ptr = (uint8_t*)pCurPtr; |
|
ptr[0] = 0; |
|
} |
|
} |
|
// context to image |
|
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow * imageHeight, ProviderReleaseData); |
|
CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, 8, 32, bytesPerRow, colorSpace, |
|
kCGImageAlphaLast | kCGBitmapByteOrder32Little, dataProvider, |
|
NULL, true, kCGRenderingIntentDefault); |
|
CGDataProviderRelease(dataProvider); |
|
UIImage* resultUIImage = [UIImage imageWithCGImage:imageRef]; |
|
// release |
|
CGImageRelease(imageRef); |
|
CGContextRelease(context); |
|
CGColorSpaceRelease(colorSpace); |
|
return resultUIImage; |
|
} |
|
|
|
@end
|
|
|