Iphone 如何使图像上的一种颜色透明?

Iphone 如何使图像上的一种颜色透明?,iphone,cocoa-touch,image,core-graphics,Iphone,Cocoa Touch,Image,Core Graphics,在我的iPhone应用程序上,我有一个UIImage实例。我想得到一个衍生的UIImage,它是第一个UIImage的结果,其中一种颜色(例如洋红)是透明的。我怎么能做到这一点呢?我自己从来没有做过类似的事情,但它看起来像是CGImageCreateWithMaskingColors在这里可能有用。不过,使用核心图形超出了我在本网站回答中所能解释的范围;查看您的文档并在Web上搜索教程 -(void)changeColor { UIImage *temp23=[UIImage image

在我的iPhone应用程序上,我有一个UIImage实例。我想得到一个衍生的UIImage,它是第一个UIImage的结果,其中一种颜色(例如洋红)是透明的。我怎么能做到这一点呢?

我自己从来没有做过类似的事情,但它看起来像是
CGImageCreateWithMaskingColors
在这里可能有用。不过,使用核心图形超出了我在本网站回答中所能解释的范围;查看您的文档并在Web上搜索教程

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

上面的代码经过测试,我使用mask将绿色改为红色

在使用了您的函数后,我找到了更简单的方法为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 5
中:

let colorMasking: [CGFloat] = [0, 0, 0, 0, 0, 0]
guard let cgImage = cgImage?.copy(maskingColorComponents: colorMasking) else { return }
image = UIImage(cgImage: cgImage)
你有一个透明背景的图像


仅此而已:)

此功能可以工作

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

嗯。尝试过之后,我不知道这些解决方案有多少个版本,我有自己的定制版本。我发现它工作得很好,但是如果您想从他的changeWhiteColorTransparent()函数中获取输出并将其传递回,它就不起作用

我的第一步是改变他的功能,接受特定的颜色和公差,以便调用者可以指定一系列的颜色,使其透明。这工作得很好,几乎没有变化,但我发现输出不是一个有效的图像,无法通过具有第二个颜色范围的相同代码

经过大量的尝试和错误,我得到了这项工作的颜色更换自己。我拒绝这样做,因为当有API来做这些事情时,这看起来太难了,但它们并不总是按照您想要的方式运行。具体来说,CGImageCreateWithMaskingColors()的输出不能用作对同一函数的另一个调用的输入。我还不知道为什么,但我认为这与阿尔法通道有关

无论如何,我的解决方案是:

- (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;
}
-(UIImage*)替换颜色:(UIColor*)图像中的颜色:(UIImage*)带容差的图像:(float)容差{
CGImageRef imageRef=[图像CGImage];
NSU整数宽度=CGImageGetWidth(imageRef);
NSU整数高度=CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceRGB();
NSU整数字节/像素=4;
NSUInteger bytesPerRow=bytesPerPixel*宽度;
NSU整数比特分量=8;
NSUTEGER bitmapByteCount=bytesPerRow*高度;
unsigned char*rawData=(unsigned char*)calloc(bitmapByteCount,sizeof(unsigned char));
CGContextRef context=CGBitmapContextCreate(原始数据、宽度、高度、,
bitsPerComponent、bytesPerRow、颜色空间、,
KCGIMAGEAlphaPremultipledLast | kCGBitmapByteOrder32Big);
CGCOLORSPACTERELEASE(色彩空间);
CGContextDrawImage(上下文,CGRectMake(0,0,宽度,高度),imageRef);
CGColorRef cgColor=[color cgColor];
const CGFloat*components=CGColorGetComponents(cgColor);
浮动r=组件[0];
浮点数g=组件[1];
浮动b=组件[2];
//浮点a=组件[3];//不需要
r=r*255.0;
g=g*255.0;
b=b*255.0;
常量浮点红色范围[2]={
最大值(r-(公差/2.0),0.0),
最小值(r+(公差/2.0),255.0)
};
常数浮点绿区[2]={
最大值(g-(公差/2.0),0.0),
最小值(g+(公差/2.0),255.0)
};
常量浮点蓝区[2]={
最大值(b-(公差/2.0),0.0),
最小值(b+(公差/2.0),255.0)
};
int byteIndex=0;
while(字节索引<位图字节计数){
无符号字符红色=原始数据[byteIndex];
无符号字符绿色=原始数据[byteIndex+1];
无符号字符蓝色=原始数据[byteIndex+2];

如果((红色>=redRange[0])&&&(红色=greenRange[0])&&(绿色=blueRange[0])&(蓝色),这是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;
}
基于,我做了一个编辑,它只使白色透明,但它使alpha基于像素的“白色”程度。这可能很方便,当你尝试从黑白图像制作遮罩时,它将在文本或形状上提供平滑的边缘

- (UIImage *)makeWhiteColorTransparentInImage:(UIImage *)image {
   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);

   int byteIndex = 0;

   while (byteIndex < bitmapByteCount) {
      unsigned char red   = rawData[byteIndex];
      unsigned char green = rawData[byteIndex + 1];
      unsigned char blue  = rawData[byteIndex + 2];
      unsigned char alpha  = rawData[byteIndex + 3];

      if (alpha == 0.0) {
          rawData[byteIndex + 3] = 0.0;
      } else {
          rawData[byteIndex + 3] = 255.0 - (red + green + blue) / 3.0;
      }

      byteIndex += 4;
    }

    CGImageRef imgref = CGBitmapContextCreateImage(context);
    UIImage *result = [UIImage imageWithCGImage:imgref];

    CGImageRelease(imgref);
    CGContextRelease(context);
    free(rawData);

    return result;
}
-(UIImage*)使白色透明图像:(UIImage*)图像{
CGImageRef imageRef=[图像CGImage];
NSU整数宽度=CGImageGetWidth(imageRef);
NSU整数高度=CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceRGB();
NSU整数字节/像素=4;
NSUInteger bytesPerRow=bytesPerPixel*宽度;
NSU整数比特分量=8;
NSUTEGER bitmapByteCount=bytesPerRow*高度;
unsigned char*rawData=(unsigned char*)calloc(bitmapByteCount,sizeof(unsigned char));
CGContextRef context=CGBitmapContextCreate(原始数据、宽度、高度、,
bitsPerComponent、bytesPerRow、颜色空间、,
KCGIMAGEAlphaPremultipledLast | kCGBitmapByteOrder32Big);
CGCOLORSPACTERELEASE(色彩空间);
CGContextDrawImage(上下文,CGRectMake(0,0,宽度,高度),imageRef);
int byteIndex=0;
while(字节索引<位图字节计数){
无符号字符红色=原始数据[byteIndex];
无符号字符绿色=原始数据[byteIndex+1];
无符号字符蓝色=原始数据[byteIndex+2];
无符号字符alpha=原始数据[byteIndex+3];
如果(α=0.0){
原始数据[byteIndex+3]=0.0;
}否则{
原始数据[byteIndex+3]=255.0-(红色+绿色+蓝色)/3.0;
}
byteIndex+=4;
}
CGImageRef imgref=CGBitmapContextCreateIma
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

    }
}
extension UIImage {
    func imageByMakingWhiteBackgroundTransparent() -> UIImage? {

        let image = UIImage(data: self.jpegData(compressionQuality: 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

    }

}
extension UIImage {
func remove(color: UIColor) -> UIImage? {
    
    let cgColor = color.cgColor
    let components = cgColor.components
    var r = components?[0] ?? 0.0
    var g = components?[1] ?? 0.0
    var b = components?[2] ?? 0.0
    
    r = r * 255.0
    g = g * 255.0
    b = b * 255.0
    
    let colorMasking: [CGFloat] = [r, r, g, g, b, b]
    
    let image = UIImage(data: self.jpegData(compressionQuality: 1.0)!)!
    let rawImageRef: CGImage = image.cgImage!
    
    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
}
}