iOS¿ª·¢-¶¨ÖƶàÑùʽ¶þάÂë¡£¶þάÂë/ÌõÐÎÂëÊǰ´ÕÕijÖÖÌØ¶¨µÄ¼¸ºÎͼÐΰ´Ò»¶¨¹æÂÉÔÚÆ½Ì¨£¨Ò»Î¬/¶þά·½ÏòÉÏ£©·Ö²¼µÄºÚ°×Ïà¼äµÄͼÐμͼ·ûºÅÐÅÏ¢¡£Ê¹ÓÃÈô¸É¸öÓë¶þ½øÖƶÔÓ¦µÄ¼¸ºÎÐÎÌåÀ´±íʾÎÄ×ÖÊýÖµÐÅÏ¢¡£
×î³£¼ûµÄ¶þάÂ빦ÄܰüÀ¨ÐÅÏ¢»ñÈ¡¡¢ÍøÕ¾Ìø×ª¡¢µçÉ̽»Òס¢ÊÖ»úÖ§¸¶µÈµÈ£¬ÆäÓµÓÐÃܶÈС¡¢ÐÅÏ¢ÈÝÁ¿´ó¡¢ÈÝ´íÄÜÁ¦Ç¿¡¢³É±¾µÍ¡¢ÖÆ×÷ÄѶȵ͵ÈÓŵ㡣ÔÚÒÆ¶¯¿ª·¢ÖУ¬¶þάÂëµÄµØÎ»Ò²Ô½À´Ô½ÖØÒª£¬ÕÆÎÕ¶þάÂëµÄ»ù±¾²Ù×÷ÊÇÖØÒªµÄ±¾ÁìÖ®Ò»¡£
ÔÚiOS7Ö®ºó£¬Æ»¹û×ÔÉí¼¯³ÉÁ˶þάÂëµÄÉú³ÉºÍ¶ÁÈ¡¹¦ÄÜ¡£Éú³É¶þάÂë°üÀ¨ÒÔϲ½Öè<†·Ÿ"/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjGhorW8yOtDb3JlSW1hZ2UvQ29yZUltYWdlLmjNt87EvP48L3A+DQo8cD4yoaLKudPDQ0lGaWx0ZXLCy761wODJ+rPJtv7OrMLrPC9wPg0KPHA+M6GittTJ+rPJtcS2/s6swuu9+NDQvNO5pKOsyrnG5Lj8x+XO+jwvcD4NCjxwPrP9wcvJz8r2yP249rK91ujWrs3io6zO0sPHu7m/ydLUttS2/s6swuu9+NDQvfjSu7K9tcTN2NW5tKbA7TwvcD4NCjxwPjGhotfUtqjS5bb+zqzC6828sLjR1cmrPC9wPg0KPHA+MqGi1Nq2/s6swuvW0NDEsuXI69SyvcfQoc28xqw8L3A+DQo8cD4zoaLU2tSyvcfNvMasz8LD5rzTyc/Su7Lj1LK9x7DXyavNvMasPC9wPg0KPGgyIGlkPQ=="¶þάÂëÉú³É">¶þάÂëÉú³É ÂëÅ©ÃÇÉú²ú´úÂëµÄͬʱÓÀÔ¶²»ÒªÍü¼Ç¾¡¿ÉÄܵĸ´Óã¬ÄÇôΪÁËʵÏÖÕâÖÖÄ¿µÄ£¬±¾ÎĵĴúÂëͨ¹ýÀà±ðÍØÕ¹UIImageµÄ·½·¨À´Íê³É¡£ÎÒÃÇÏÈÉùÃ÷²¢ÊµÏÖÒ»¸öÀà·½·¨ÓÃÀ´½ÓÊÕ¶þάÂë´æ´¢Êý¾ÝÒÔ¼°¶þάÂë³ß´çµÄ·½·¨£º
+ (UIImage *)imageOfQRFromURL: (NSString *)networkAddress codeSize: (CGFloat)codeSize {
if (!networkAddress|| (NSNull *)networkAddress == [NSNull null]) { return nil; }
codeSize = [self validateCodeSize: codeSize];
CIImage * originImage = [self createQRFromAddress: networkAddress];
UIImage * result = [UIImage imageWithCIImage: originImage];
return result;
}
ÔÚÉÏÃæµÄ´úÂëÀïÃæ£¬ÎÒÃÇ×ܹ²×öÁËËļþÊÂÇ飺ÑéÖ¤´æ´¢ÐÅÏ¢µÄÓÐЧÐÔ£»ÑéÖ¤¶þάÂë³ß´çµÄºÏÀí´óС£»Ê¹Óô洢ÐÅÏ¢Éú³É¶þάÂ룻½«¶þάÂëת³ÉUIImage·µ»Ø¡£ÕâЩ·½·¨µÄʵÏÖ·Ö±ðÈçÏ£º
/*! ÑéÖ¤¶þάÂë³ß´çºÏ·¨ÐÔ*/
+ (CGFloat)validateCodeSize: (CGFloat)codeSize
{
codeSize = MAX(160, codeSize);
codeSize = MIN(CGRectGetWidth([UIScreen mainScreen].bounds) - 80, codeSize);
return codeSize;
}
/*! ÀûÓÃϵͳÂ˾µÉú³É¶þάÂëͼ*/
+ (CIImage *)createQRFromAddress: (NSString *)networkAddress
{
NSData * stringData = [networkAddress dataUsingEncoding: NSUTF8StringEncoding];
CIFilter * qrFilter = [CIFilter filterWithName: @"CIQRCodeGenerator"];
[qrFilter setValue: stringData forKey: @"inputMessage"];
[qrFilter setValue: @"H" forKey: @"inputCorrectionLevel"];
return qrFilter.outputImage;
}
ps£º
ÉÏÃæµÄ´úÂëÉú³ÉÁËÒ»¸ö´ÖÂԵĶþάÂëͼ£¬ÎÒÃÇÐèÒª¶ÔͼƬÔÙ½øÐÐÒ»´Î´¦Àí£¬Ê¹ÆäÇåÎú»¯¡£ÒòΪ£¬ÎÒÃÇÐèÒªÁíÍâÒ»¸öÀà±ð·½·¨£º¶ÔÓÚCIFilterÏëÒª¸ü½øÒ»²½Á˽⣬¿ÉÒÔÔÚxcodeÖÐʹÓÿì½Ý¼üshift+command+0´ò¿ªÎĵµ£¬È»ºóËÑË÷core image filter reference»ñÈ¡¸ü¶àÂ˾µµÄʹÓ÷½·¨£¬ÕâЩÂ˾µ¿ÉÒÔÓÃÀ´ÊµÏÖÀàËÆÃÀͼÐãÐãµÄÐÞͼ¹¦ÄÜ¡£
/*! ¶ÔͼÏñ½øÐÐÇåÎú»¯´¦Àí*/
+ (UIImage *)excludeFuzzyImageFromCIImage: (CIImage *)image size: (CGFloat)size
{
CGRect extent = CGRectIntegral(image.extent);
CGFloat scale = MIN(size / CGRectGetWidth(extent), size / CGRectGetHeight(extent));
size_t width = CGRectGetWidth(extent) * scale;
size_t height = CGRectGetHeight(extent) * scale;
//´´½¨»Ò¶ÈÉ«µ÷¿Õ¼ä
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGContextRef bitmapRef = CGBitmapContextCreate(nil, width, height, 8, 0, colorSpace, (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);
CGImageRef scaledImage = CGBitmapContextCreateImage(bitmapRef);
CGContextRelease(bitmapRef);
CGImageRelease(bitmapImage);
CGColorSpaceRelease(colorSpace);
return [UIImage imageWithCGImage: scaledImage];
}
ÄÇôÕâʱºò£¬ÎÒÃǰÑ+(UIImage *)imageOfQRFromURL: codeSize: µÄ×îºó¸Ä³É
UIImage * result =[self excludeFuzzyImageFromCIImage: originImage size: codeSize];
ʾÀýÍê³ÉºóÉú³ÉµÄ¶þάÂëЧ¹ûͼÈçÏ£º
µ¥Ò»µÄºÚ°×É«¶þάÂë²¢²»Ò»¶¨×ÜÄÜÂú×㿪·¢µÄÐèÇó»òÕß˵Áìµ¼µÄÐèÇ󡣺ñÈÏÖÔÚµÄÓ¦Óúܶ๦ÄܽçÃæÉ϶¼ÔÚ³¯×Å΢ÐÅѧϰ£¬Õâ¾Í°üÀ¨Á˸ü¶àÉ«²Ê£¬¸ü¶àÑùʽµÄ¶þάÂë¡£
±¾ÎĽ«´Ó ÑÕÉ«¡¢¶þάÂëÖÐÐÄСͼ°¸ ÕâÁ½µãÈëÊÖ½²½âÈçºÎÖÆ×÷ÀàËÆÎ¢ÐÅÉú³ÉÎҵĶþάÂëµÄÑùʽ¡£
×Ô¶¨Òå¶þάÂëÑÕÉ«µÄʵÏÖ˼·ÊÇ£¬±éÀúÉú³ÉµÄ¶þάÂëµÄÏñËØµã£¬½«ÆäÖÐΪ°×É«µÄÏñËØµãÌî³äΪ͸Ã÷É«£¬·Ç°×É«ÔòÌî³äΪÎÒÃÇ×Ô¶¨ÒåµÄÑÕÉ«¡£µ«ÊÇ£¬ÕâÀïµÄ°×É«²¢²»µ¥µ¥Ö¸´¿°×É«£¬rgbÖµ¸ßÓÚÒ»¶¨ÊýÖµµÄ»ÒÉ«ÎÒÃÇÒ²¿ÉÒÔÊÓ×÷°×É«´¦Àí¡£ÔÚÕâÀïÎÒ¶Ô°×É«µÄ¶¨ÒåΪrgbÖµ¸ßÓÚ0xd0d0d0µÄÑÕɫֵΪ°×É«£¬Õâ¸öÖµ²¢²»ÊÇÈ·¶¨µÄ£¬´ó¼Ò¿ÉÒÔ×Ô¼ºÉèÖ᣻ùÓÚÑÕÉ«µÄÉèÖã¬ÎÒÃǽ«ÔÓÐÉú³É¶þάÂëµÄ·½·¨½Ó¿Ú¸Ä³ÉÕâÑù£º
+ (UIImage *)imageOfQRFromURL: (NSString *)networkAddress codeSize: (CGFloat)codeSize red: (NSUInteger)red green: (NSUInteger)green blue: (NSUInteger)blue {
if (!networkAddress || (NSNull *)networkAddress == [NSNull null]) { return nil; }
/** ÑÕÉ«²»¿ÉÒÔÌ«½Ó½ü°×É«*/
NSUInteger rgb = (red << 16) + (green << 8) + blue;
NSAssert((rgb & 0xffffff00) <= 0xd0d0d000, @"The color of QR code is two close to white color than it will diffculty to scan");
codeSize = [self validateCodeSize: codeSize];
CIImage * originImage = [self createQRFromAddress: networkAddress];
UIImage * progressImage = [self excludeFuzzyImageFromCIImage: originImage size: codeSize]; //µ½ÁËÕâÀï¶þάÂëÒѾ¿ÉÒÔ½øÐÐɨÃèÁË
UIImage * effectiveImage = [self imageFillBlackColorAndTransparent: progressImage red: red green: green blue: blue]; //½øÐÐÑÕÉ«äÖȾºóµÄ¶þάÂë
return effectiveImage;
}
Ïà½ÏÓÚÇ°ÃæµÄ´úÂ룬¶àÁËÁ½¸ö²½Ö裺ÅжÏrgbµÄÓÐЧֵ£»¶Ô¶þάÂë½øÐÐÑÕÉ«äÖȾ¡£ÑÕÉ«äÖȾµÄ¹ý³Ì°üÀ¨»ñȡͼÏñµÄλͼÉÏÏÂÎÄ¡¢ÏñËØÌæ»»¡¢¶þ½øÖÆÍ¼Ïñת»»µÈ²Ù×÷£¬¾ßÌå´úÂëÈçÏ£º
/*! ¶ÔÉú³É¶þάÂëͼÏñ½øÐÐÑÕÉ«Ìî³ä*/
+ (UIImage *)imageFillBlackColorAndTransparent: (UIImage *)image red: (NSUInteger)red green: (NSUInteger)green blue: (NSUInteger)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);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
CGContextDrawImage(context, (CGRect){(CGPointZero), (image.size)}, image.CGImage);
//±éÀúÏñËØ
int pixelNumber = imageHeight * imageWidth;
[self fillWhiteToTransparentOnPixel: rgbImageBuf pixelNum: pixelNumber red: red green: green blue: blue];
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow, ProviderReleaseData);
CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, 8, 32, bytesPerRow, colorSpace, kCGImageAlphaLast | kCGBitmapByteOrder32Little, dataProvider, NULL, true, kCGRenderingIntentDefault);
UIImage * resultImage = [UIImage imageWithCGImage: imageRef];
CGImageRelease(imageRef);
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
return resultImage;
}
/*! ±éÀúËùÓÐÏñËØµã½øÐÐÑÕÉ«Ìæ»»*/
+ (void)fillWhiteToTransparentOnPixel: (uint32_t *)rgbImageBuf pixelNum: (int)pixelNum red: (NSUInteger)red green: (NSUInteger)green blue: (NSUInteger)blue {
uint32_t * pCurPtr = rgbImageBuf;
for (int i = 0; i < pixelNum; i++, pCurPtr++) {
if ((*pCurPtr & 0xffffff00) < 0xd0d0d000) {
uint8_t * ptr = (uint8_t *)pCurPtr;
ptr[3] = red;
ptr[2] = green;
ptr[1] = blue;
} else {
//½«°×É«±ä³É͸Ã÷É«
uint8_t * ptr = (uint8_t *)pCurPtr;
ptr[0] = 0;
}
}
}
void ProviderReleaseData(void * info, const void * data, size_t size) {
free((void *)data);
}
ps£º
ÔÚÐ޸ĴúÂë֮ǰ£¬Ó¦¸ÃÏëÇå³þÊÇ·ñÐèҪɾ³ýÔÓдúÂë¡£ÀàËÆÕâÖÖ¶þάÂëµÄÀ©Õ¹£¬¾ÉµÄ¶þάÂëÉú³É½Ó¿Ú¿ÉÒÔÁôÏÂÀ´£¬È»ºóÔÚÆäÖе÷Óöà²ÎÊýµÄÈ«Äܹ¹ÔìÆ÷(Designated Initializer)¡£
Õâʱºò¾àÀë΢ÐÅ»¹²îһС²½£¬ÎÒÃÇÒªÔÚ¶þάÂëµÄÖÐÐÄλÖòåÈëÎÒÃǵÄСͷÏñ£¬×îÖ±½ÓµÄ·½Ê½ÊǼÓÔØÍêÎÒÃǵÄÍ·Ïñºó£¬Ö±½ÓdrawInRect:¡£ÕâÖÖʵÏÖ·½·¨ÊÇÕýÈ·µÄ£¬µ«ÊÇÔÚÎÒÃÇ»ÉÏȥ֮ǰ£¬ÎÒÃÇ»¹ÐèÒª¶ÔͼÏñ½øÐÐÔ²½Ç´¦Àí¡££¨Ê¡ÊµĿÉÄÜÖ±½ÓÓÃimageView¼ÓÔØÍ·Ïñ£¬È»ºóÉèÖÃÍ·ÏñµÄcornerRadius£¬Õâ¸öÒ²ÄÜʵÏÖЧ¹û£©¡£
µ½ÁËÕâ¸öʱºò£¬ÎÒÃÇÐèÒªÒ»¸ö¸ü¶à²ÎÊýµÄ¶þάÂëÉú³É·½·¨½Ó¿ÚÁË£¬Õâ´ÎÐÂÔöµÄ²ÎÊýÓ¦¸Ã°üÀ¨²åÈëͼƬ¡¢Ô²½Ç°ë¾¶ÕâЩ²ÎÊý£¬Òò´Ë·½·¨ÈçÏ£º
+ (UIImage *)imageOfQRFromURL: (NSString *)networkAddress codeSize: (CGFloat)codeSize red: (NSUInteger)red green: (NSUInteger)green blue: (NSUInteger)blue insertImage: (UIImage *)insertImage roundRadius: (CGFloat)roundRadius {
if (!networkAddress || (NSNull *)networkAddress == [NSNull null]) { return nil; }
/** ÑÕÉ«²»¿ÉÒÔÌ«½Ó½ü°×É«*/
NSUInteger rgb = (red << 16) + (green << 8) + blue;
NSAssert((rgb & 0xffffff00) <= 0xd0d0d000, @"The color of QR code is two close to white color than it will diffculty to scan");
codeSize = [self validateCodeSize: codeSize];
CIImage * originImage = [self createQRFromAddress: networkAddress];
UIImage * progressImage = [self excludeFuzzyImageFromCIImage: originImage size: codeSize]; //µ½ÁËÕâÀï¶þάÂëÒѾ¿ÉÒÔ½øÐÐɨÃèÁË
UIImage * effectiveImage = [self imageFillBlackColorAndTransparent: progressImage red: red green: green blue: blue]; //½øÐÐÑÕÉ«äÖȾºóµÄ¶þάÂë
return [self imageInsertedImage: effectiveImage insertImage: insertImage radius: roundRadius];
}
Õâ´ÎµÄÉú³É·½·¨Í¬ÑùÒ²Ö»ÐèÒª½øÐÐÒ»´Î¶îÍâµÄµ÷Ó÷½·¨²Ù×÷£¬ÔÚ²åÈëͼƬµÄʱºòÎÒÃÇÐèҪעÒ⣬ÀàËÆÎ¢ÐŵÄͼÖÐͼ¶þάÂëÖмäµÄСͷÏñÊÇÓÐÒ»¸öÔ²½ÇµÄ°×É«±ßÔµµÄ£¬Õâ¸ö±ßÔµµÄ¼ÓÈëÈÃÍ·ÏñÏÔʾµÄ¸ü¼Ó×ÔÈ»¡£ÄÇôҪÍê³ÉÕâ¸öЧ¹û£¬ÎÒ¶îÍâÔÚÏîÄ¿ÖмÓÈëÁËÒ»ÕŰ×É«±³¾°µÄСͼ£¬Í¬Ñù¶ÔÕâÕÅͼƬ½øÐÐÔ²½Ç»¯´¦Àí£¬È»ºó¼ÓÔÚÍ·ÏñµÄÏÂÃæ¡£×÷ΪͷÏñÏ·½µÄ°×É«±³¾°Í¼Ïñ³ß´çÓ¦¸Ã´óÓÚÍ·Ïñͼ¡£ÖÆ×÷»ÖлЧ¹ûµÄ¾ßÌåʵÏÖÈçÏ£º
/*! ÔÚ¶þάÂëÔͼÖÐÐÄλÖòåÈëÔ²½ÇͼÏñ*/
+ (UIImage *)imageInsertedImage: (UIImage *)originImage insertImage: (UIImage *)insertImage radius: (CGFloat)radius {
if (!insertImage) { return originImage; }
insertImage = [UIImage imageOfRoundRectWithImage: insertImage size: insertImage.size radius: radius];
UIImage * whiteBG = [UIImage imageNamed: @"whiteBG"];
whiteBG = [UIImage imageOfRoundRectWithImage: whiteBG size: whiteBG.size radius: radius];
//°×É«±ßÔµ¿í¶È
const CGFloat whiteSize = 2.f;
CGSize brinkSize = CGSizeMake(originImage.size.width / 4, originImage.size.height / 4);
CGFloat brinkX = (originImage.size.width - brinkSize.width) * 0.5;
CGFloat brinkY = (originImage.size.height - brinkSize.height) * 0.5;
CGSize imageSize = CGSizeMake(brinkSize.width - 2 * whiteSize, brinkSize.height - 2 * whiteSize);
CGFloat imageX = brinkX + whiteSize;
CGFloat imageY = brinkY + whiteSize;
UIGraphicsBeginImageContext(originImage.size);
[originImage drawInRect: (CGRect){ 0, 0, (originImage.size) }];
[whiteBG drawInRect: (CGRect){ brinkX, brinkY, (brinkSize) }];
[insertImage drawInRect: (CGRect){ imageX, imageY, (imageSize) }];
UIImage * resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultImage;
}
+ (UIImage *)imageOfRoundRectWithImage: (UIImage *)image size: (CGSize)size radius: (CGFloat)radius
{
if (!image) { return nil; }
const CGFloat width = size.width;
const CGFloat height = size.height;
radius = MAX(5.f, radius);
radius = MIN(10.f, radius);
UIImage * img = image;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedFirst);
CGRect rect = CGRectMake(0, 0, width, height);
//»æÖÆÔ²½Ç
CGContextBeginPath(context);
addRoundRectToPath(context, rect, radius, img.CGImage);
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
img = [UIImage imageWithCGImage: imageMasked];
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
CGImageRelease(imageMasked);
return img;
}
ps£º
ͼÏñ»æÖÆÔ²½ÇÊÇͨ¹ýÔÚͼÏñÉÏÏÂÎÄÖл³öÔ²½Ç¾ØÐεÄ·¾¶£¬È»ºó½øÐвüô£¬ÕâÑù¾ÍÄÜʵÏÖͼƬµÄÔ²½Ç»¯¡£
+ (UIImage *)imageOfQRFromURL: (NSString *)networkAddress {
return [self imageOfQRFromURL: networkAddress codeSize: 100.0f red: 0 green: 0 blue: 0 insertImage: nil roundRadius: 0.f];
}