在iOS中合并两个PNG图像而不会失去透明度

时间:2013-05-29 17:34:56

标签: ios objective-c

我有两个png格式图像,并且都定义了透明度。我需要将这些合并到一个新的png图像中,但不会丢失结果中的任何透明度。

+(UIImage *) combineImage:(UIImage *)firstImage  colorImage:(UIImage *)secondImage
{
   UIGraphicsBeginImageContext(firstImage.size);
   CGContextRef context = UIGraphicsGetCurrentContext();

   CGContextSaveGState(context);

   CGContextTranslateCTM(context, 0, firstImage.size.height);
   CGContextScaleCTM(context, 1.0, -1.0);
   CGRect rect = CGRectMake(0, 0, firstImage.size.width, firstImage.size.height);
   // draw white background to preserve color of transparent pixels
   CGContextSetBlendMode(context, kCGBlendModeDarken);
   [[UIColor whiteColor] setFill];
   CGContextFillRect(context, rect);

   CGContextSaveGState(context);
   CGContextRestoreGState(context);

   // draw original image
   CGContextSetBlendMode(context, kCGBlendModeDarken);
   CGContextDrawImage(context, rect, firstImage.CGImage);

   // tint image (loosing alpha) - the luminosity of the original image is preserved
   CGContextSetBlendMode(context, kCGBlendModeDarken); 
   //CGContextSetAlpha(context, .85);
   [[UIColor colorWithPatternImage:secondImage] setFill];
   CGContextFillRect(context, rect);


   CGContextSaveGState(context);
   CGContextRestoreGState(context);

   // mask by alpha values of original image
   CGContextSetBlendMode(context, kCGBlendModeDestinationIn);
   CGContextDrawImage(context, rect, firstImage.CGImage);

   // image drawing code here
   CGContextRestoreGState(context);
   UIImage *coloredImage = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();

   return coloredImage;
}

需要任何帮助来改进我的代码性能。

提前致谢

2 个答案:

答案 0 :(得分:3)

首先,对CGContextSaveGStateCGContextRestoreGState的调用,一个接一个地调用,两者之间没有任何内容,对你没有任何作用。有关CGContextSaveGStateCGContextRestoreGState执行操作的解释,请参阅此其他答案:CGContextSaveGState vs UIGraphicsPushContext

现在,通过“合并”图像,我并不是100%清楚你的意思。如果您只想在另一个上面绘制一个,并使用标准混合模式混合它们的颜色,那么您只需要更改这些混合模式调用以传递kCGBlendModeNormal(或者只是忽略对{{1}的调用如果你想用第一个图像的alpha值掩盖第二个图像,那么你应该用普通混合模式绘制第二个图像,然后切换到CGContextSetBlendMode并绘制第一个图像。

我担心我不确定你在尝试用中间的图像着色代码做什么,但我的直觉是你不会最终需要它。您应该能够通过绘制一个图像,然后设置混合模式,然后绘制另一个图像来获得大多数合并效果。

此外,您在评论“白色背景以保留透明像素的颜色”下所获得的代码可能会在整个图像中绘制白色,但它肯定不会保留透明像素的颜色,这使得那些像素白色!您应该删除该代码,除非您真的希望“透明”颜色为白色。

答案 1 :(得分:0)

使用Vinay的问题和Aaron的评论中给出的代码来开发这种混合,覆盖任意数量的图像:

/**
 Returns the images overplayed atop each other according to their array position, with the first image being bottom-most, and the last image being top-most.
 - parameter images: The images to overlay.
 - parameter size: The size of resulting image. Any images not matching this size will show a loss in fidelity.
 */
func combinedImageFromImages(images: [UIImage], withSize size: CGSize) -> UIImage
{
  // Setup the graphics context (allocation, translation/scaling, size)
  UIGraphicsBeginImageContext(size)       
  let context = UIGraphicsGetCurrentContext()
  CGContextTranslateCTM(context, 0, size.height)
  CGContextScaleCTM(context, 1.0, -1.0)
  let rect = CGRectMake(0, 0, size.width, size.height)

  // Combine the images
  for image in images {
    CGContextDrawImage(context, rect, image.CGImage)
  }
  let combinedImage = UIGraphicsGetImageFromCurrentImageContext()
  UIGraphicsEndImageContext()

  return combinedImage
}