在我的iPhone应用程序上,我有一个UIImage实例.我想得到一个UIImage,它是第一个UIImage的结果,其中一个颜色(例如品红色)变得透明.我怎样才能做到这一点?
好.经过尝试我不知道这些解决方案有多少个版本,我有自己的定制版本.我发现@yubenyi的解决方案效果很好,但是如果你想从他的changeWhiteColorTransparent()函数中获取输出并将其传回,则它不起作用.
我的第一步是改变他的功能以接受特定的颜色和容差,以便调用者可以指定一系列颜色以使其透明.这很好,几乎没有变化,但我发现输出不是一个有效的图像,用于传递具有第二个颜色范围的相同代码.
经过大量的试验和错误,我通过自己进行颜色替换来实现这一点.我拒绝这一点,因为当有API来做这件事时似乎太辛苦了,但它们并不总是按照你想要的方式行事.具体来说,CGImageCreateWithMaskingColors()的输出不能用作对同一函数的另一个调用的输入.我无法找出原因,但我认为这与alpha通道有关.
无论如何,我的解决方案是:
- (UIImage*) replaceColor:(UIColor*)color inImage:(UIImage*)image withTolerance:(float)tolerance { CGImageRef imageRef = [image CGImage]; NSUInteger width = CGImageGetWidth(imageRef); NSUInteger height = CGImageGetHeight(imageRef); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); NSUInteger bytesPerPixel = 4; NSUInteger bytesPerRow = bytesPerPixel * width; NSUInteger bitsPerComponent = 8; NSUInteger bitmapByteCount = bytesPerRow * height; unsigned char *rawData = (unsigned char*) calloc(bitmapByteCount, sizeof(unsigned char)); CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGColorSpaceRelease(colorSpace); CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); CGColorRef cgColor = [color CGColor]; const CGFloat *components = CGColorGetComponents(cgColor); float r = components[0]; float g = components[1]; float b = components[2]; //float a = components[3]; // not needed r = r * 255.0; g = g * 255.0; b = b * 255.0; const float redRange[2] = { MAX(r - (tolerance / 2.0), 0.0), MIN(r + (tolerance / 2.0), 255.0) }; const float greenRange[2] = { MAX(g - (tolerance / 2.0), 0.0), MIN(g + (tolerance / 2.0), 255.0) }; const float blueRange[2] = { MAX(b - (tolerance / 2.0), 0.0), MIN(b + (tolerance / 2.0), 255.0) }; int byteIndex = 0; while (byteIndex < bitmapByteCount) { unsigned char red = rawData[byteIndex]; unsigned char green = rawData[byteIndex + 1]; unsigned char blue = rawData[byteIndex + 2]; if (((red >= redRange[0]) && (red <= redRange[1])) && ((green >= greenRange[0]) && (green <= greenRange[1])) && ((blue >= blueRange[0]) && (blue <= blueRange[1]))) { // make the pixel transparent // rawData[byteIndex] = 0; rawData[byteIndex + 1] = 0; rawData[byteIndex + 2] = 0; rawData[byteIndex + 3] = 0; } byteIndex += 4; } CGImageRef imgref = CGBitmapContextCreateImage(context); UIImage *result = [UIImage imageWithCGImage:imgref]; CGImageRelease(imgref); CGContextRelease(context); free(rawData); return result; }
这是对yubenyi的代码的调整,可以使用多次传递.它在处理之前通过将图像转换为未压缩的jpeg来剥离alpha通道.还添加了一些关于颜色范围选择如何工作的注释.
-(UIImage *)changeWhiteColorTransparent: (UIImage *)image { //convert to uncompressed jpg to remove any alpha channels //this is a necessary first step when processing images that already have transparency image = [UIImage imageWithData:UIImageJPEGRepresentation(image, 1.0)]; CGImageRef rawImageRef=image.CGImage; //RGB color range to mask (make transparent) R-Low, R-High, G-Low, G-High, B-Low, B-High const double colorMasking[6] = {222, 255, 222, 255, 222, 255}; UIGraphicsBeginImageContext(image.size); CGImageRef maskedImageRef=CGImageCreateWithMaskingColors(rawImageRef, colorMasking); //iPhone translation CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0.0, image.size.height); CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0); CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, image.size.width, image.size.height), maskedImageRef); UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); CGImageRelease(maskedImageRef); UIGraphicsEndImageContext(); return result; }
-(void)changeColor { UIImage *temp23=[UIImage imageNamed:@"leaf.png"]; CGImageRef ref1=[self createMask:temp23]; const float colorMasking[6] = {1.0, 2.0, 1.0, 1.0, 1.0, 1.0}; CGImageRef New=CGImageCreateWithMaskingColors(ref1, colorMasking); UIImage *resultedimage=[UIImage imageWithCGImage:New]; } -(CGImageRef)createMask:(UIImage*)temp { CGImageRef ref=temp.CGImage; int mWidth=CGImageGetWidth(ref); int mHeight=CGImageGetHeight(ref); int count=mWidth*mHeight*4; void *bufferdata=malloc(count); CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; CGContextRef cgctx = CGBitmapContextCreate (bufferdata,mWidth,mHeight, 8,mWidth*4, colorSpaceRef, kCGImageAlphaPremultipliedFirst); CGRect rect = {0,0,mWidth,mHeight}; CGContextDrawImage(cgctx, rect, ref); bufferdata = CGBitmapContextGetData (cgctx); CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bufferdata, mWidth*mHeight*4, NULL); CGImageRef savedimageref = CGImageCreate(mWidth,mHeight, 8, 32, mWidth*4, colorSpaceRef, bitmapInfo,provider , NULL, NO, renderingIntent); CFRelease(colorSpaceRef); return savedimageref; }
上面的代码经过测试,我使用蒙版将绿色更改为红色
这个功能可以工作!
-(UIImage *)changeWhiteColorTransparent: (UIImage *)image { CGImageRef rawImageRef=image.CGImage; const float colorMasking[6] = {222, 255, 222, 255, 222, 255}; UIGraphicsBeginImageContext(image.size); CGImageRef maskedImageRef=CGImageCreateWithMaskingColors(rawImageRef, colorMasking); { //if in iphone CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0.0, image.size.height); CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0); } CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, image.size.width, image.size.height), maskedImageRef); UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); CGImageRelease(maskedImageRef); UIGraphicsEndImageContext(); return result; }
使用你的功能后,我找到了更简单的方法来为UIImage制作透明背景:)
例如,您有带黑色背景的PNG图像,并且您希望在屏幕上使此背景透明.
你可以试试这个:
UIImage * image = [UIImage imageNamed:@"image.png"]; const CGFloat colorMasking[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; image = [UIImage imageWithCGImage: CGImageCreateWithMaskingColors(image.CGImage, colorMasking)];
你有透明背景的图像.
就这样 :)
Swift 4 :(用于白色蒙版)
extension UIImage { func imageByMakingWhiteBackgroundTransparent() -> UIImage? { let image = UIImage(data: UIImageJPEGRepresentation(self, 1.0)!)! let rawImageRef: CGImage = image.cgImage! let colorMasking: [CGFloat] = [222, 255, 222, 255, 222, 255] UIGraphicsBeginImageContext(image.size); let maskedImageRef = rawImageRef.copy(maskingColorComponents: colorMasking) UIGraphicsGetCurrentContext()?.translateBy(x: 0.0,y: image.size.height) UIGraphicsGetCurrentContext()?.scaleBy(x: 1.0, y: -1.0) UIGraphicsGetCurrentContext()?.draw(maskedImageRef!, in: CGRect.init(x: 0, y: 0, width: image.size.width, height: image.size.height)) let result = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return result } }