真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

iOS定制多樣式二維碼

二維碼/條形碼是按照某種特定的幾何圖形按一定規(guī)律在平臺(tái)(一維/二維方向上)分布的黑白相間的圖形紀(jì)錄符號(hào)信息。使用若干個(gè)與二進(jìn)制對(duì)應(yīng)的幾何形體來(lái)表示文字?jǐn)?shù)值信息。

專業(yè)領(lǐng)域包括網(wǎng)站建設(shè)、網(wǎng)站制作、商城網(wǎng)站建設(shè)、微信營(yíng)銷、系統(tǒng)平臺(tái)開(kāi)發(fā), 與其他網(wǎng)站設(shè)計(jì)及系統(tǒng)開(kāi)發(fā)公司不同,創(chuàng)新互聯(lián)建站的整合解決方案結(jié)合了幫做網(wǎng)絡(luò)品牌建設(shè)經(jīng)驗(yàn)和互聯(lián)網(wǎng)整合營(yíng)銷的理念,并將策略和執(zhí)行緊密結(jié)合,為客戶提供全網(wǎng)互聯(lián)網(wǎng)整合方案。

iOS 定制多樣式二維碼

最常見(jiàn)的二維碼功能包括信息獲取、網(wǎng)站跳轉(zhuǎn)、電商交易、手機(jī)支付等等,其擁有密度小、信息容量大、容錯(cuò)能力強(qiáng)、成本低、制作難度低等優(yōu)點(diǎn)。在移動(dòng)開(kāi)發(fā)中,二維碼的地位也越來(lái)越重要,掌握二維碼的基本操作是重要的本領(lǐng)之一。

在iOS7之后,蘋果自身集成了二維碼的生成和讀取功能。生成二維碼包括以下步驟

  • 導(dǎo)入CoreImage/CoreImage.h頭文件
  • 使用CIFilter濾鏡類生成二維碼
  • 對(duì)生成的二維碼進(jìn)行加工,使其更清晰

除了上述三個(gè)步驟之外,我們還可以對(duì)二維碼進(jìn)行進(jìn)一步的拓展處理

  • 自定義二維碼圖案顏色
  • 在二維碼中心插入圓角小圖片
  • 在圓角圖片下面加上一層圓角白色圖片

二維碼生成

碼農(nóng)們生產(chǎn)代碼的同時(shí)永遠(yuǎn)不要忘記盡可能的復(fù)用,那么為了實(shí)現(xiàn)這種目的,本文的代碼通過(guò)類別拓展UIImage的方法來(lái)完成。我們先聲明并實(shí)現(xiàn)一個(gè)類方法用來(lái)接收二維碼存儲(chǔ)數(shù)據(jù)以及二維碼尺寸的方法:

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

在上面的代碼里面,我們總共做了四件事情:驗(yàn)證存儲(chǔ)信息的有效性;驗(yàn)證二維碼尺寸的合理大小;使用存儲(chǔ)信息生成二維碼;將二維碼轉(zhuǎn)成UIImage返回。這些方法的實(shí)現(xiàn)分別如下:

/*! 驗(yàn)證二維碼尺寸合法性*/
+ (CGFloat)validateCodeSize: (CGFloat)codeSize
{
  codeSize = MAX(160, codeSize);
  codeSize = MIN(CGRectGetWidth([UIScreen mainScreen].bounds) - 80, codeSize);
  return codeSize;
}

/*! 利用系統(tǒng)濾鏡生成二維碼圖*/
+ (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;
}

/! 驗(yàn)證二維碼尺寸合法性/
- (CGFloat)validateCodeSize: (CGFloat)codeSize
{
  codeSize = MAX(160, codeSize);
  codeSize = MIN(CGRectGetWidth([UIScreen mainScreen].bounds) - 80, codeSize);
  return codeSize;
}

/! 利用系統(tǒng)濾鏡生成二維碼圖/
- (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:對(duì)于CIFilter想要更進(jìn)一步了解,可以在xcode中使用快捷鍵shift+command+0打開(kāi)文檔,然后搜索core image filter reference獲取更多濾鏡的使用方法,這些濾鏡可以用來(lái)實(shí)現(xiàn)類似美圖秀秀的修圖功能。

上面的代碼生成了一個(gè)粗略的二維碼圖,我們需要對(duì)圖片再進(jìn)行一次處理,使其清晰化。因?yàn)?,我們需要另外一個(gè)類別方法:

/! 對(duì)圖像進(jìn)行清晰化處理/
- (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;

  //創(chuàng)建灰度色調(diào)空間
  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];
}

那么這時(shí)候,我們把+(UIImage *)imageOfQRFromURL: codeSize:的最后改成

UIImage * result =[self excludeFuzzyImageFromCIImage: originImage size: codeSize];

示例完成后生成的二維碼效果圖如下:

iOS 定制多樣式二維碼

二維碼拓展

單一的黑白色二維碼并不一定總能滿足開(kāi)發(fā)的需求或者說(shuō)領(lǐng)導(dǎo)的需求。好比現(xiàn)在的應(yīng)用很多功能界面上都在朝著微信學(xué)習(xí),這就包括了更多色彩,更多樣式的二維碼。本文將從顏色、二維碼中心小圖案這兩點(diǎn)入手講解如何制作類似微信生成我的二維碼的樣式。

自定義二維碼顏色的實(shí)現(xiàn)思路是,遍歷生成的二維碼的像素點(diǎn),將其中為白色的像素點(diǎn)填充為透明色,非白色則填充為我們自定義的顏色。但是,這里的白色并不單單指純白色,rgb值高于一定數(shù)值的灰色我們也可以視作白色處理。在這里我對(duì)白色的定義為rgb值高于0xd0d0d0的顏色值為白色,這個(gè)值并不是確定的,大家可以自己設(shè)置。基于顏色的設(shè)置,我們將原有生成二維碼的方法接口改成這樣:

+ (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];   //到了這里二維碼已經(jīng)可以進(jìn)行掃描了
  UIImage * effectiveImage = [self imageFillBlackColorAndTransparent: progressImage red: red green: green blue: blue]; //進(jìn)行顏色渲染后的二維碼
  return effectiveImage;
}

相較于前面的代碼,多了兩個(gè)步驟:判斷rgb的有效值;對(duì)二維碼進(jìn)行顏色渲染。顏色渲染的過(guò)程包括獲取圖像的位圖上下文、像素替換、二進(jìn)制圖像轉(zhuǎn)換等操作,具體代碼如下:

/*! 對(duì)生成二維碼圖像進(jìn)行顏色填充*/
+ (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;
}

/! 遍歷所有像素點(diǎn)進(jìn)行顏色替換/
+ (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:在修改代碼之前,應(yīng)該想清楚是否需要?jiǎng)h除原有代碼。類似這種二維碼的擴(kuò)展,舊的二維碼生成接口可以留下來(lái),然后在其中調(diào)用多參數(shù)的全能構(gòu)造器Designated Initializer。

iOS 定制多樣式二維碼

這時(shí)候距離微信還差一小步,我們要在二維碼的中心位置插入我們的小頭像,最直接的方式是加載完我們的頭像后,直接drawInRect:這種實(shí)現(xiàn)方法是正確的,但是在我們畫上去之前,我們還需要對(duì)圖像進(jìn)行圓角處理。(省事的可能直接用imageView加載頭像,然后設(shè)置頭像的cornerRadius,這個(gè)也能實(shí)現(xiàn)效果)。

到了這個(gè)時(shí)候,我們需要一個(gè)更多參數(shù)的二維碼生成方法接口了,這次新增的參數(shù)應(yīng)該包括插入圖片、圓角半徑這些參數(shù),因此方法如下:

+ (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];   //到了這里二維碼已經(jīng)可以進(jìn)行掃描了
  UIImage * effectiveImage = [self imageFillBlackColorAndTransparent: progressImage red: red green: green blue: blue]; //進(jìn)行顏色渲染后的二維碼
  return [self imageInsertedImage: effectiveImage insertImage: insertImage radius: roundRadius];
}

這次的生成方法同樣也只需要進(jìn)行一次額外的調(diào)用方法操作,在插入圖片的時(shí)候我們需要注意,類似微信的圖中圖二維碼中間的小頭像是有一個(gè)圓角的白色邊緣的,這個(gè)邊緣的加入讓頭像顯示的更加自然。那么要完成這個(gè)效果,我額外在項(xiàng)目中加入了一張白色背景的小圖,同樣對(duì)這張圖片進(jìn)行圓角化處理,然后加在頭像的下面。作為頭像下方的白色背景圖像尺寸應(yīng)該大于頭像圖。制作畫中畫效果的具體實(shí)現(xiàn)如下:

/! 在二維碼原圖中心位置插入圓角圖像/
+ (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:圖像繪制圓角是通過(guò)在圖像上下文中畫出圓角矩形的路徑,然后進(jìn)行裁剪,這樣就能實(shí)現(xiàn)圖片的圓角化。

iOS 定制多樣式二維碼

在代碼中,對(duì)中心位置的頭像限制尺寸為二維碼的四分之一,這個(gè)尺寸下的頭像不失清晰度,而且圖片尺寸也不至于遮蓋了二維碼的存儲(chǔ)數(shù)據(jù)。上面的方法都可以在頭文件中開(kāi)發(fā)方法接口使用,這將實(shí)現(xiàn)這些代碼的復(fù)用。另外,所有本文中寫到的生成二維碼的接口都應(yīng)該在頭文件中聲明,并且在其實(shí)現(xiàn)中調(diào)用全能方法(不應(yīng)當(dāng)僅僅是構(gòu)造器需要遵循Designated Initializer的原則):

+ (UIImage *)imageOfQRFromURL: (NSString *)networkAddress 
{
  return [self imageOfQRFromURL: networkAddress codeSize: 100.0f red: 0 green: 0 blue: 0 insertImage: nil roundRadius: 0.f];
}

以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持創(chuàng)新互聯(lián)!


新聞標(biāo)題:iOS定制多樣式二維碼
網(wǎng)站網(wǎng)址:http://weahome.cn/article/pehhjs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部