web-dev-qa-db-ja.com

iOSでプログラムで画像に色を付けるにはどうすればよいですか?

画像に色参照を付けます。結果は、Photoshopの乗算ブレンディングモードのようになります。whitestint

alt text

色の値を連続的に変更します。

フォローアップ: ImageViewのdrawRect:メソッドにこれを行うためのコードを入れますか?

いつものように、コードスニペットは、リンクとは対照的に、私の理解に大いに役立ちます。

更新:コードでUIImageViewをサブクラス化Ramin推奨。

これをView ControllerのviewDidLoad:に配置します:

[self.lena setImage:[UIImage imageNamed:kImageName]];
[self.lena setOverlayColor:[UIColor blueColor]];
[super viewDidLoad];

画像は表示されますが、色付けされていません。また、他の画像をロードし、IBで画像を設定し、View ControllerでsetNeedsDisplay:を呼び出してみました。

更新:drawRect:は呼び出されていません。

最終更新: imageViewが適切に設定された古いプロジェクトを見つけたので、Raminのコードをテストできました。

最終、最終更新:

Core Graphicsについて学習したばかりの人のために、おそらく最も簡単に機能するものを以下に示します。

サブクラス化されたUIViewで:

- (void)drawRect:(CGRect)rect {

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColor(context, CGColorGetComponents([UIColor colorWithRed:0.5 green:0.5 blue:0 alpha:1].CGColor)); // don't make color too saturated

    CGContextFillRect(context, rect); // draw base

    [[UIImage imageNamed:@"someImage.png"] drawInRect: rect blendMode:kCGBlendModeOverlay alpha:1.0]; // draw image
}
87
willc2

まず、UIImageViewをサブクラス化し、drawRectメソッドをオーバーライドします。クラスには、ブレンドカラーと、カラーが変更されたときに再描画を強制するカスタムセッターを保持するためのUIColorプロパティ(overlayColorと呼びましょう)が必要です。このようなもの:

- (void) setOverlayColor:(UIColor *)newColor {
   if (overlayColor)
     [overlayColor release];

   overlayColor = [newColor retain];
   [self setNeedsDisplay]; // fires off drawRect each time color changes
}

DrawRectメソッドでは、最初に画像を描画してから、適切なブレンドモードとともに、目的の色で塗りつぶされた長方形でオーバーレイします。これは次のようなものです。

- (void) drawRect:(CGRect)area
{
  CGContextRef context = UIGraphicsGetCurrentContext();
  CGContextSaveGState(context);

  // Draw picture first
  //
  CGContextDrawImage(context, self.frame, self.image.CGImage);

  // Blend mode could be any of CGBlendMode values. Now draw filled rectangle
  // over top of image.
  //
  CGContextSetBlendMode (context, kCGBlendModeMultiply);
  CGContextSetFillColor(context, CGColorGetComponents(self.overlayColor.CGColor));      
  CGContextFillRect (context, self.bounds);
  CGContextRestoreGState(context);
}

通常、描画を最適化するには、実際の描画をdrawRectに渡された領域のみに制限しますが、色が変わるたびに背景画像を再描画する必要があるため、全体を更新する必要があります。

それを使用するには、オブジェクトのインスタンスを作成し、imageプロパティ(UIImageViewから継承)を画像に、overlayColorをUIColor値に設定します(ブレンドレベルはアルファ値を変更することで調整できます)あなたが伝える色の)。

44
Ramin

IOS7では、UIImageViewにtintColorプロパティを導入し、UIImageにrenderingModeを導入しました。 iOS7でUIImageに色を付けるには、次を実行するだけです。

UIImageView* imageView = …
UIImage* originalImage = …
UIImage* imageForRendering = [originalImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
imageView.image = imageForRendering;
imageView.tintColor = [UIColor redColor]; // or any color you want to tint it with
76
Toland Hon

アルファで画像に色をつけたいと思い、次のクラスを作成しました。問題が見つかった場合はお知らせください。

クラスにCSTintedImageViewという名前を付けました。以前の返信で述べたように、UIViewdrawRect:メソッドを呼び出さないため、UIImageViewから継承します。 UIImageViewクラスにあるような初期化子を指定しました。

使用法:

CSTintedImageView * imageView = [[CSTintedImageView alloc] initWithImage:[UIImage imageNamed:@"image"]];
imageView.tintColor = [UIColor redColor];

CSTintedImageView.h

@interface CSTintedImageView : UIView

@property (strong, nonatomic) UIImage * image;
@property (strong, nonatomic) UIColor * tintColor;

- (id)initWithImage:(UIImage *)image;

@end

CSTintedImageView.m

#import "CSTintedImageView.h"

@implementation CSTintedImageView

@synthesize image=_image;
@synthesize tintColor=_tintColor;

- (id)initWithImage:(UIImage *)image
{
    self = [super initWithFrame:CGRectMake(0, 0, image.size.width, image.size.height)];

    if(self)
    {
        self.image = image;

        //set the view to opaque
        self.opaque = NO;
    }

    return self;
}

- (void)setTintColor:(UIColor *)color
{
    _tintColor = color;

    //update every time the tint color is set
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();    

    //resolve CG/iOS coordinate mismatch
    CGContextScaleCTM(context, 1, -1);
    CGContextTranslateCTM(context, 0, -rect.size.height);

    //set the clipping area to the image
    CGContextClipToMask(context, rect, _image.CGImage);

    //set the fill color
    CGContextSetFillColor(context, CGColorGetComponents(_tintColor.CGColor));
    CGContextFillRect(context, rect);    

    //blend mode overlay
    CGContextSetBlendMode(context, kCGBlendModeOverlay);

    //draw the image
    CGContextDrawImage(context, rect, _image.CGImage);    
}

@end
26
user263865

簡単な説明(このトピックに関する調査の後)。 Apple doc here は次のことを明確に述べています:

UIImageViewクラスは、ディスプレイに画像を描画するために最適化されています。 UIImageViewは、そのサブクラスのdrawRect:メソッドを呼び出しません。サブクラスにカスタム描画コードを含める必要がある場合は、代わりにUIViewクラスをサブクラス化する必要があります。

UIImageViewサブクラスでそのメソッドをオーバーライドしようとして時間を無駄にしないでください。代わりにUIViewで始めてください。

26
mattorb

これは非常に便利です。PhotoshopFrameworkは、Objective-Cで画像を操作するための強力なライブラリです。これは、Adobe Photoshopユーザーが使い慣れているのと同じ機能を提供するために開発されました。例:RGB 0-255を使用した色の設定、ブレンドファイラーの適用、変換...

オープンソースです、ここにプロジェクトリンクがあります: https://sourceforge.net/projects/photoshopframew/

UIImage * image = mySourceImage;
UIColor * color = [UIColor yellowColor];  
UIGraphicsBeginImageContext(image.size);
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height) blendMode:kCGBlendModeNormal alpha:1];
UIBezierPath * path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, image.size.width, image.size.height)];
[color setFill];
[path fillWithBlendMode:kCGBlendModeMultiply alpha:1]; //look up blending modes for your needs
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//use newImage for something
4
gngrwzrd

特に別の目的ですでにQuartzCoreを使用している場合は特に、画像の色付けを実装する別の方法があります。これは、 同様の質問 に対する私の答えでした。

QuartzCoreのインポート:

#import <QuartzCore/QuartzCore.h>

透明なCALayerを作成し、色付けする画像のサブレイヤーとして追加します。

CALayer *sublayer = [CALayer layer];
[sublayer setBackgroundColor:[UIColor whiteColor].CGColor];
[sublayer setOpacity:0.3];
[sublayer setFrame:toBeTintedImage.frame];
[toBeTintedImage.layer addSublayer:sublayer];

プロジェクトフレームワークリストにQuartzCoreを追加します(まだない場合)。そうしないと、次のようなコンパイラエラーが発生します。

Undefined symbols for architecture i386: "_OBJC_CLASS_$_CALayer"
3
lekksi

UIImageViewクラスをサブクラス化して「drawRect:が呼び出されていない」でスタックしようとする場合は、UIImageViewクラスの場合は「drawRect:」メソッドが呼び出されないため、代わりにUIViewクラスをサブクラス化する必要があります。詳細はこちら: drawImageはUIImageViewのサブクラスで呼び出されていません

2
pierre

Swift 2.0、

    let image: UIImage! = UIGraphicsGetImageFromCurrentImageContext()

    imgView.image = imgView.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)

    imgView.tintColor = UIColor(red: 51/255.0, green: 51/255.0, blue: 

51/255.0, alpha: 1.0)
1
yazh

また、パフォーマンスのために合成画像をキャッシュし、drawRect:でレンダリングすることを検討し、ダーティフラグが実際にダーティである場合は更新することもできます。頻繁に変更することもありますが、ドローが来て汚れていない場合があるため、キャッシュから単純に更新できます。メモリがパフォーマンスよりも問題である場合、これは無視できます:)

0
Steve Riggins

私が考えることができる唯一のことは、希望する色で長方形のほとんど透明なビューを作成し、それをサブビューとして追加することで画像ビューの上に置くことです。あなたが想像するようにこれが本当に画像に色合いを付けるかどうかはわかりませんが、画像にハックして特定の色を他の色に選択的に置き換える方法はわかりません...私にはかなり野心的です。

例えば:

UIImageView *yourPicture = (however you grab the image);
UIView *colorBlock = [[UIView alloc] initWithFrame:yourPicture.frame];
//Replace R G B and A with values from 0 - 1 based on your color and transparency
colorBlock.backgroundColor = [UIColor colorWithRed:R green:G blue:B alpha:A];
[yourPicture addSubView:colorBlock];

UIColorのドキュメント:

colorWithRed:green:blue:alpha:

Creates and returns a color object using the specified opacity and RGB component values.

+ (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha

Parameters

red    - The red component of the color object, specified as a value from 0.0 to 1.0.

green  - The green component of the color object, specified as a value from 0.0 to 1.0.

blue   - The blue component of the color object, specified as a value from 0.0 to 1.0.



alpha  - The opacity value of the color object, specified as a value from 0.0 to 1.0.

Return Value

The color object. The color information represented by this object is in the device RGB colorspace. 
0
Tim Bowen

私はこれのためにオープンソース化したライブラリを持っています: ios-image-filters

0
esilver

この目的のためにマクロを作成しました。

#define removeTint(view) \
if ([((NSNumber *)[view.layer valueForKey:@"__hasTint"]) boolValue]) {\
for (CALayer *layer in [view.layer sublayers]) {\
if ([((NSNumber *)[layer valueForKey:@"__isTintLayer"]) boolValue]) {\
[layer removeFromSuperlayer];\
break;\
}\
}\
}

#define setTint(view, tintColor) \
{\
if ([((NSNumber *)[view.layer valueForKey:@"__hasTint"]) boolValue]) {\
removeTint(view);\
}\
[view.layer setValue:@(YES) forKey:@"__hasTint"];\
CALayer *tintLayer = [CALayer new];\
tintLayer.frame = view.bounds;\
tintLayer.backgroundColor = [tintColor CGColor];\
[tintLayer setValue:@(YES) forKey:@"__isTintLayer"];\
[view.layer addSublayer:tintLayer];\
}

使用するには、単に呼び出すだけです:

setTint(yourView, yourUIColor);
//Note: include opacity of tint in your UIColor using the alpha channel (RGBA), e.g. [UIColor colorWithRed:0.5f green:0.0 blue:0.0 alpha:0.25f];

濃淡を削除するときは、次のように呼び出します。

removeTint(yourView);
0
Albert Renshaw