当前位置:  开发笔记 > 编程语言 > 正文

如何在UIImage上制作一种透明的颜色?

如何解决《如何在UIImage上制作一种透明的颜色?》经验,为你挑选了6个好方法。

在我的iPhone应用程序上,我有一个UIImage实例.我想得到一个UIImage,它是第一个UIImage的结果,其中一个颜色(例如品红色)变得透明.我怎样才能做到这一点?



1> PKCLsoft..:

好.经过尝试我不知道这些解决方案有多少个版本,我有自己的定制版本.我发现@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;
}


好方法!顺便提一下,当你提供[UIColor whiteColor]时,它不会起作用,因为它是一种特殊类型UIColor的子类.当你做[UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f]而它确实有效.可能会为下一个人节省一些调试时间.
这是我最喜欢的答案,因为可以容忍.注意:公差在0到255之间,所以它在1以下没有效果.平滑的版本现在将是完美的!

2> bgolson..:

这是对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;
}



3> 小智..:
-(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;
}   

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


你的代码工作得很好.但是如何将红色变为绿色或任何其他颜色
谢谢你的好功能.但是我没有得到真正的结果,直到我没有做出这个改变:kCGImageAlphaPremultipliedFirst - > kCGImageAlphaPremultipliedLast在那个函数给了我真实的结果之后.:) 谢谢.

4> 小智..:

这个功能可以工作!

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


这使我的整个图像透明.我错过了什么吗?

5> Vitaly..:

使用你的功能后,我找到了更简单的方法来为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)];

你有透明背景的图像.

就这样 :)



6> 小智..:

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

    }
}

推荐阅读
落单鸟人
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有