iOS 定制多样式二维码

2020-01-18 22:02:52刘景俊

到了这个时候,我们需要一个更多参数的二维码生成方法接口了,这次新增的参数应该包括插入图片、圆角半径这些参数,因此方法如下:


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