简体   繁体   English

如何在iOS中为图像的白色背景上色

[英]How to color-tint the white background of an image in iOS

I am porting a card-melding-game from Android to iOS (see https://play.google.com/store/apps/details?id=com.pipperpublishing.fivekings ). 我正在将纸牌融合游戏从Android移植到iOS(请参阅https://play.google.com/store/apps/details?id=com.pipperpublishing.fivekings )。 I want to tint the wild cards in yellow (as an aid to game play for novices). 我想将通配符染成黄色(以帮助新手玩游戏)。

In Android this is brainlessly easy, using cards with black on white. 在Android中,使用黑底白字的卡片非常容易。

    static final int TINT_COLOR = Color.parseColor("#FFFF66"); //light yellow
    static final PorterDuff.Mode PORTER_DUFF_MODE = PorterDuff.Mode.DARKEN;
...

        if (highlightWildCard != null) {
            //mutate so this setting will not carry through to other rounds or to the Computer cards when shown
            this.getDrawable().mutate();
            this.getDrawable().setColorFilter(TINT_COLOR, PORTER_DUFF_MODE);
        }

I can't find an equivalent way to do this in iOS. 我找不到在iOS中执行此操作的等效方法。 I have tried this: 我已经试过了:

class CardView : UIImageView {
        static let TINT_COLOR = UIColor.yellowColor() //FIXME: UIColorFromRGB(0xFFFF66); //light yellow
...
        if (highlightWildCard != nil) {
            //for tintColor to be applied, have to replace with an image template - note this creates a new image
            self.image = self.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
            self.backgroundColor = CardView.TINT_COLOR
        }

but this just paints the whole card yellow. 但这只会将整张卡片涂成黄色。

And I have tried using CGContextSetBlendMode, but just got a bunch of errors that I didn't understand. 我曾尝试使用CGContextSetBlendMode,但遇到了一些我不理解的错误。

Hopefully you iOS experts can point me in the right direction (and hopefully not one involving creating a separate set of tinted cards ;) 希望您的iOS专家可以为我指明正确的方向(希望没有一个人涉及创建单独的有色卡片;)

UPDATE: I have tried using this excellent extension from this post: How to tint a transparent PNG image in iPhone? 更新:我已尝试使用本文中的出色扩展: 如何在iPhone中着色透明的PNG图像? but this seems to leave the card untinted. 但这似乎使卡没有染色。

You can use the CoreImage framework for that. 您可以CoreImage使用CoreImage框架。

I can show you how to do it in Objective-C, so I hope this helps. 我可以向您展示如何在Objective-C中做到这一点,希望对您有所帮助。 You should be able to translate it to swift, or you can just use it directly using a bridging header. 您应该可以将其转换为swift,也可以直接使用桥接头直接使用它。

First you'll need a to create a CoreImage context. 首先,您需要创建一个CoreImage上下文。 It is best to initialize it once - so save a reference to it with a property: 最好将其初始化一次-因此请使用属性保存对它的引用:

@property (strong, nonatomic) CIContext *ciContext;
...
self.ciContext = [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer : @NO}];

Now the interesting part - using a CIColorMatrix filter to shift the white. 现在有趣的部分-使用CIColorMatrix滤镜移动白色。 Here's a method which does just that (notice it uses the ciContext we've previously created): 这是一种做到这一点的方法(请注意,它使用了我们先前创建的ciContext):

-(UIImage*)filteredImageFromImage:(UIImage*)sourceImage withColor:(UIColor*)color
{
    size_t componentCount = CGColorGetNumberOfComponents(color.CGColor);
    if (componentCount < 4)
    {
        return sourceImage;
    }

    CIImage *inputCIImage = [CIImage imageWithCGImage:sourceImage.CGImage];
    CGRect extent = [inputCIImage extent];

    CGFloat r, g, b, a;
    [color getRed:&r green:&g blue:&b alpha:&a];

    CIFilter *colorMatrixFilter = [CIFilter filterWithName:@"CIColorMatrix"];
    [colorMatrixFilter setDefaults];
    [colorMatrixFilter setValue:inputCIImage forKey:kCIInputImageKey];
    [colorMatrixFilter setValue:[CIVector vectorWithX:r Y:0 Z:0 W:0] forKey:@"inputRVector"];
    [colorMatrixFilter setValue:[CIVector vectorWithX:0 Y:g Z:0 W:0] forKey:@"inputGVector"];
    [colorMatrixFilter setValue:[CIVector vectorWithX:0 Y:0 Z:b W:0] forKey:@"inputBVector"];

    CGImageRef cgiimage = [self.ciContext createCGImage:colorMatrixFilter.outputImage fromRect:extent];
    UIImage *newImage = [UIImage imageWithCGImage:cgiimage scale:[[UIScreen mainScreen] scale] orientation:sourceImage.imageOrientation];
    CGImageRelease(cgiimage);

    return newImage;
}

Finally, to tint your card to yellow: 最后,将您的卡片染成黄色:

UIImage *cardImage = [self filteredImageFromImage:[UIImage imageNamed:@"card"] withColor:[UIColor yellowColor]];

Edit: 编辑:

Here's how to use it in swift with a bridging header: 以下是通过桥接标头快速使用它的方法:

  1. Add a new Objective-C class. 添加一个新的Objective-C类。 Let's call it ImageFilter. 我们称之为ImageFilter。

The header file: 头文件:

// ImageFilter.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h> 

@interface ImageFilter : NSObject
-(UIImage*)filteredImageFromImage:(UIImage*)sourceImage withColor:(UIColor*)color;
@end

The implementation file: 执行文件:

// ImageFilter.m

#import "ImageFilter.h"
#import <CoreImage/CoreImage.h>


@interface ImageFilter()
@property (strong, nonatomic) CIContext *ciContext;
@end

@implementation ImageFilter

- (instancetype)init
{
    self = [super init];
    if (self != nil)
    {
        self.ciContext = [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer : @NO}];
    }
    return self;
}

-(UIImage*)filteredImageFromImage:(UIImage*)sourceImage withColor:(UIColor*)color
{
    size_t componentCount = CGColorGetNumberOfComponents(color.CGColor);
    if (componentCount < 4)
    {
        return sourceImage;
    }

    CIImage *inputCIImage = [CIImage imageWithCGImage:sourceImage.CGImage];
    CGRect extent = [inputCIImage extent];

    CGFloat r, g, b, a;
    [color getRed:&r green:&g blue:&b alpha:&a];

    CIFilter *colorMatrixFilter = [CIFilter filterWithName:@"CIColorMatrix"];
    [colorMatrixFilter setDefaults];
    [colorMatrixFilter setValue:inputCIImage forKey:kCIInputImageKey];
    [colorMatrixFilter setValue:[CIVector vectorWithX:r Y:0 Z:0 W:0] forKey:@"inputRVector"];
    [colorMatrixFilter setValue:[CIVector vectorWithX:0 Y:g Z:0 W:0] forKey:@"inputGVector"];
    [colorMatrixFilter setValue:[CIVector vectorWithX:0 Y:0 Z:b W:0] forKey:@"inputBVector"];

    CGImageRef cgiimage = [self.ciContext createCGImage:colorMatrixFilter.outputImage fromRect:extent];
    UIImage *newImage = [UIImage imageWithCGImage:cgiimage scale:[[UIScreen mainScreen] scale] orientation:sourceImage.imageOrientation];
    CGImageRelease(cgiimage);

    return newImage;
}

@end
  1. In your bridging file (usually YourProject-Bridging-Header.h which Xcode will ask and create automatically when you add a new Objective-C file to your project) import our new file: 在您的桥接文件(通常是YourProject-Bridging-Header.h中,当您向项目中添加新的Objective-C文件时,Xcode会自动询问并创建)导入我们的新文件:

    #import ImageEffect.h

Also, don't forget to make sure the "YourProject-Bridging-Header.h" is specified under "Objective-C Bridging Header in your target's build settings. 另外,不要忘记确保在目标的构建设置中的“ Objective-C桥接头”下指定了“ YourProject-Bridging-Header.h”。

  1. Use it in your swift code: 在您的快速代码中使用它:

    let imageFilter: ImageFilter = ImageFilter() 让imageFilter:ImageFilter = ImageFilter()

     let cardImage = imageFilter.filteredImageFromImage(UIImage(named: "card"), withColor: UIColor.yellowColor()); 

Note: the code formatting went a bit crazy on me, don't know why. 注意:代码格式让我有些疯狂,不知道为什么。 It's causing the last bit of code in swift to not show as a code block properly... 这导致迅速的最后一部分代码无法正确显示为代码块...

I tried using How to tint a transparent PNG image in iPhone? 我尝试使用如何在iPhone中着色透明的PNG图像? to do the tinting, but that just darkened the red and black on the cards and left the white untouched. 进行着色,但这只会使卡片上的红色和黑色变暗,而白色则保持不变。 However, I switched to CGBlendMode of .Darken (instead of .Color) and that achieved that I was looking for - the white turns to the yellow color and the red/blacl is acceptably darkened also. 但是,我切换到.Darken(而不是.Color)的CGBlendMode,并且实现了我一直在寻找的东西-白色变成了黄色,红色/ blacl也被可接受地变暗了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM