SimpleBoxes

Tinted image for UIImage

[画像]画面に表示するイメージ画像に色付けしたい……。

iOS のアプリケーションでハイライト状態などを示すため、生成した画像イメージに対して色付けしたいときがあります。

UIView には tintColor というプロパティがあって、色付けが簡単にできそうなのですが、イメージを表示する UIImageViewtintColor を設定しても何も変わりません。

そこで以下のようなヘルパークラスを用意して利用しています。

@interface SBLImageHelper
/**
 *  Generates an image which is tinted with a given color.
 *  @param image - an image to be tinted
 *  @param color - tint color
 *  @return an instance of UIImage
 */
+ (UIImage *)tintedImageFromImage:(UIImage *)image
                        withColor:(UIColor *)color;
@end


@implementation SBLImageHelper

+ (UIImage *)tintedImageFromImage:(UIImage *)image
                        withColor:(UIColor *)color
{
  UIImage *output = nil;
  CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);

  if (UIGraphicsBeginImageContextWithOptions != NULL)
  {
    UIGraphicsBeginImageContextWithOptions(image.size,
                                           NO,
                                           image.scale);
  }
  else
  {
    UIGraphicsBeginImageContext(image.size);
  }

  CGContextRef context = UIGraphicsGetCurrentContext();

  // -- flipping geometry
  CGContextTranslateCTM(context, 0, image.size.height);
  CGContextScaleCTM(context, 1.0, -1.0);

  // -- setting up blend mode
  CGContextSetBlendMode(context, kCGBlendModeNormal);

  // -- first drawing the image
  CGContextDrawImage(context, rect, image.CGImage);

  // -- then setting up mask and fill the color
  CGContextClipToMask(context, rect, image.CGImage);
  CGContextSetFillColorWithColor(context, color.CGColor);
  CGContextFillRect(context, rect);

  output = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();

  return output;
}

@end

次のように使います。

UIColor *tintColor = [[UIColor redColor] colorWithAlphaComponent:0.5];
UIImage *originalImage = [UIImage imageNamed:@"sample"];
UIImage *tintedImage = [SBLImageHelper tintedImageFromImage:originalImage
                                                  withColor:tintColor];

Objective-C にはカテゴリーという既存のクラスを拡張するための仕組みがありますが、すでにあるメソッドと同じ名前のメソッドを追加すると、どっちのメソッドが利用されるか分からなくなってしまうという強烈な副作用があります。

ですので、個人的にはあまりオススメしませんが、UIImage のカテゴリーとして拡張するバージョンだと以下のようになるでしょうか。

@interface UIImage (SBLImageHelper)
/**
 *  Generates an image which is tinted with a given color.
 *  @param color - tint color
 *  @return an instance of UIImage
 */
- (UIImage *)imageWithTintColor:(UIColor *)color;

@end


@implementation UIImage (SBLImageHelper)

- (UIImage *)imageWithTintColor:(UIColor *)color
{
  UIImage *output = nil;
  CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);

  if (UIGraphicsBeginImageContextWithOptions != NULL)
  {
    UIGraphicsBeginImageContextWithOptions(self.size,
                                           NO,
                                           self.scale);
  }
  else
  {
    UIGraphicsBeginImageContext(self.size);
  }

  CGContextRef context = UIGraphicsGetCurrentContext();

  // -- flipping geometry
  CGContextTranslateCTM(context, 0, self.size.height);
  CGContextScaleCTM(context, 1.0, -1.0);

  // -- setting up blend mode
  CGContextSetBlendMode(context, kCGBlendModeNormal);

  // -- first drawing the image
  CGContextDrawImage(context, rect, self.CGImage);

  // -- then setting up mask and fill the color
  CGContextClipToMask(context, rect, self.CGImage);
  CGContextSetFillColorWithColor(context, color.CGColor);
  CGContextFillRect(context, rect);

  output = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();

  return output;
}

@end

この記事は qiita.com の内容を再掲載したものです。

スポンサーリンク

<< スイス・チューリッヒに引っ越しました :: さぁ、楽しいバグ取りの時間だ — バグに対してのワークフロー >>