iOS:将RGB滤镜应用于灰度PNG

4
我有一个灰度宝石的顶视图。(PNG格式,所以具有alpha组件)
我想要从这个图像创建12个不同颜色的小按钮。
为了整洁起见,我想在代码中完成而不是在艺术软件中进行操作。
有人能提供一种方法(甚至一些代码)来实现这一点吗?
PS:我知道如何在GL中使用大量代码来完成这个任务,但我希望能够使用核心图形/核心动画更简单的方式实现。
编辑:感谢下面答案的完美解决方案。
    CGSize targetSize = (CGSize){100,100};
    UIImage* image;
    {
        CGRect rect = (CGRect){ .size = targetSize };

        UIGraphicsBeginImageContext( targetSize );
        {
            CGContextRef X = UIGraphicsGetCurrentContext();

            UIImage* uiGem = [UIImage imageNamed: @"GemTop_Dull.png"];

            // draw gem
            [uiGem drawInRect: rect];

            // overlay a red rectangle
            CGContextSetBlendMode( X, kCGBlendModeColor ) ;
            CGContextSetRGBFillColor ( X,  0.9, 0, 0,  1 );
            CGContextFillRect ( X, rect );

            // redraw gem 
            [uiGem drawInRect: rect
                    blendMode: kCGBlendModeDestinationIn
                        alpha: 1. ];

            image = UIGraphicsGetImageFromCurrentImageContext();
        }
        UIGraphicsEndImageContext();
    }

我对你的代码示例中看似多余的 {} 很好奇 - 它们是做什么用的? - Rhubarb
它们使代码更清晰/封装变量 - P i
如果您想支持Retina图像,请确保使用UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0.0);而不是UIGraphicsBeginImageContext( targetSize );。参数NO0.0分别表示使用不透明上下文(YES或NO值)和比例因子(0.0表示设备比例因子,任何其他值表示显式比例因子)。 - Thomas Verbeek
3个回答

4

最简单的方法是将图像绘制到RGB颜色空间的CGBitmapContext中,使用CGContextSetBlendMode设置kCGBlendModeColor,然后用纯色覆盖它(例如使用CGContextFillRect)。


我认为这只会引起在这里提到的问题:http://forums.macrumors.com/showthread.php?t=547339 - P i
1
如果CGContextFillRect擦除了alpha通道,请尝试使用kCGBlendModeDestinationIn将原始图像绘制在顶部以重新应用它。 - Anomie
我刚刚尝试了一下(我已经修改了我的问题)... 但是我仍然无法摆脱那些红色背景。有什么想法吗? - P i
1
@Pi:drawInRect:没有遵守您在底层上下文中设置的混合模式。请尝试使用drawInRect:blendMode:alpha: - Anomie
太棒了!谢谢你——我永远也想不到这个! - P i

1
使用灰度值来索引从所需结果的最暗到最亮颜色的梯度,可以获得最好的外观效果。不幸的是,我不知道如何在核心图形中实现这一点的具体细节。

你可以在Core Image包中使用CIColorMap来实现这个功能。 - bcattle
例如,请查看此问题 - bcattle

0

这是对问题答案的改进,也是@Anomie的实现。

首先,在您的UIButton类或视图控制器的开头放置此代码。它将从UIColor转换为RGBA值,稍后您将需要使用它。

typedef enum { R, G, B, A } UIColorComponentIndices;


@implementation UIColor (EPPZKit)

- (CGFloat)redRGBAValue {
    return CGColorGetComponents(self.CGColor)[R];
}

- (CGFloat)greenRGBAValue  {
    return CGColorGetComponents(self.CGColor)[G];
}

- (CGFloat)blueRGBAValue  {
    return CGColorGetComponents(self.CGColor)[B];
}

- (CGFloat)alphaRGBAValue  {
    return CGColorGetComponents(self.CGColor)[A];
}

@end

现在,请确保您在IB中拥有自定义图像按钮,带有灰度图像和正确的框架。这比通过编程创建自定义图像按钮要好得多且更容易,因为:

  • 您可以让IB加载图像,而不必手动加载
  • 您可以调整按钮并在IB中直观地看到它
  • 您的IB将在运行时更像您的应用程序
  • 您不必手动设置框架

假设您的按钮在IB中(底部附近将支持以编程方式创建),请将此方法添加到您的视图控制器或按钮类中:

- (UIImage*)customImageColoringFromButton:(UIButton*)customImageButton fromColor:(UIColor*)color {
    UIImage *customImage = [customImageButton.imageView.image copy];

    UIGraphicsBeginImageContext(customImageButton.imageView.frame.size); {
        CGContextRef X = UIGraphicsGetCurrentContext();

        [customImage drawInRect: customImageButton.imageView.frame];

        // Overlay a colored rectangle
        CGContextSetBlendMode( X, kCGBlendModeColor) ;
        CGContextSetRGBFillColor ( X, color.redRGBAValue, color.greenRGBAValue, color.blueRGBAValue, color.alphaRGBAValue);
        CGContextFillRect ( X, customImageButton.imageView.frame);

        // Redraw
        [customImage drawInRect:customImageButton.imageView.frame blendMode: kCGBlendModeDestinationIn alpha: 1.0];

        customImage = UIGraphicsGetImageFromCurrentImageContext();
    }
    UIGraphicsEndImageContext();

    return customImage;
}

你需要在视图控制器或按钮子类的设置方法中调用它,并将该按钮的imageView设置为它:
[myButton.imageView setImage:[self customImageColoringFromButton:myButton fromColor:desiredColor]];

如果您不使用IB创建按钮,请使用此方法:

- (UIImage*)customImageColoringFromImage:(UIImage*)image fromColor:(UIColor*)color fromFrame:(CGRect)frame {
    UIImage *customImage = [image copy];

    UIGraphicsBeginImageContext(frame.size); {
        CGContextRef X = UIGraphicsGetCurrentContext();

        [customImage drawInRect: frame];

        // Overlay a colored rectangle
        CGContextSetBlendMode( X, kCGBlendModeColor) ;
        CGContextSetRGBFillColor ( X, color.redRGBAValue, color.greenRGBAValue, color.blueRGBAValue, color.alphaRGBAValue);
        CGContextFillRect ( X, frame);

        // Redraw
        [customImage drawInRect:frame blendMode: kCGBlendModeDestinationIn alpha: 1.0];

        customImage = UIGraphicsGetImageFromCurrentImageContext();
    }
    UIGraphicsEndImageContext();

    return customImage;
}

并使用以下方式调用:

[self.disclosureButton.imageView setImage:[self customImageColoringFromImage:[UIImage imageNamed:@"GemTop_Dull.png"] fromColor:desiredColor fromFrame:desiredFrame]];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接