【问题标题】:UIImageView filter image into solid colorUIImageView 过滤图片成纯色
【发布时间】:2013-08-19 21:39:43
【问题描述】:

我有一些带有透明背景的彩色图标。我希望能够根据程序的状态自动显示那些(纯灰色)的平面版本。

我可以使用 Core Image 滤镜来做到这一点吗?还有其他方法吗?

【问题讨论】:

    标签: iphone ios core-graphics core-image


    【解决方案1】:

    子类化并创建自己的 UIImageView(或具有 UIImageView 属性的 UIView)并覆盖 drawRect,您需要将上下文剪辑到图像蒙版,然后用纯色填充:

    - (void)drawRect:(CGRect)rect;
    {
      CGRect bounds = [self bounds];
      [[UIColor grayColor] setFill];
      CGContextRef context = UIGraphicsGetCurrentContext();
      CGContextClipToMask(context, bounds, [image CGImage]);
      CGContextFillRect(context, bounds);
    }
    

    【讨论】:

      【解决方案2】:

      我想我以前做过同样的事情,我有一些彩色图标,但我需要保持形状并将颜色更改为单色。所以我写了一个 UIImage 的扩展。

      这是代码,希望对你有帮助。

      UIImage+MonoImage.h

      //
      //  UIImage+MonoImage.h
      //  ShiftScheduler
      //
      //  Created by Zhang Jiejing on 12-2-11.
      //  Copyright (c) 2012. All rights reserved.
      //
      
      #import <UIKit/UIKit.h>
      
      @interface UIImage (MonoImage)
      
      // This function create a Image Context and draw the image with mask
      // then clip the context to mask
      // then fill the color user choosed.
      // that can create a image shape with specify color icon.
      + (UIImage *) generateMonoImage: (UIImage *)icon withColor:(UIColor *)color;
      @end
      

      UIImage+MonoImage.m

      //
      //  UIImage+MonoImage.m
      //  ShiftScheduler
      //
      //  Created by Jiejing Zhang on 12-2-11.
      //  Copyright (c) 2012. All rights reserved.
      //
      
      #import "UIImage+MonoImage.h"
      
      @implementation UIImage (MonoImage)
      
      + (UIImage *) generateMonoImage: (UIImage *)icon withColor:(UIColor *)color
      {
          UIImage *finishImage;
          CGImageRef alphaImage = CGImageRetain(icon.CGImage);
          CGColorRef colorref = CGColorRetain(color.CGColor);
      
          UIGraphicsBeginImageContext(icon.size);
          CGContextRef ctx = UIGraphicsGetCurrentContext();
      
          CGRect imageArea = CGRectMake (0, 0,
                                         icon.size.width, icon.size.height);
      
          // Don't know why if I don't translate the CTM, the image will be a *bottom* up
          // aka, head on bottom shape, so I need use TranlateCTM and ScaleCTM to let
          // all y-axis to be rotated.
          CGFloat height = icon.size.height;
          CGContextTranslateCTM(ctx, 0.0, height);
          CGContextScaleCTM(ctx, 1.0, -1.0);
      
          CGContextClipToMask(ctx, imageArea , alphaImage);
      
          CGContextSetFillColorWithColor(ctx, colorref);
          CGContextFillRect(ctx, imageArea);
          CGImageRelease(alphaImage);
          CGColorRelease(colorref);
      
          finishImage = UIGraphicsGetImageFromCurrentImageContext();
          UIGraphicsEndImageContext();
          return finishImage;
      }
      
      
      @end
      

      【讨论】:

      • 您可以将 UIColor 作为平面颜色传递,输出应该是您想要的。
      • 哦,你必须缩放和平移,因为 Core Graphics 使用与 UIKit 不同的坐标系。
      • 是的,我在编写这段代码后发现了这一点,但我没有找到不进行转换的方法。如果你有这样的方法,请告诉我。 :)
      【解决方案3】:

      这是我创建的 UIView 子类。非常感谢 Oliver 指出这一点。我以为你当时不能继承 UIImageView 。

      @interface SolidColorImageView : UIView
      @property (nonatomic, strong) UIImage * image;
      @property (nonatomic) BOOL enabled;
      @end
      
      
      
      
      
      
      @implementation SolidColorImageView
      
      - (void)setImage:(UIImage *)image {
          _image = image;
          [self setNeedsDisplay];
      }
      
      - (void)setEnabled:(BOOL)enabled {
          _enabled = enabled;
          [self setNeedsDisplay];
      }
      
      - (void)drawRect:(CGRect)rect;
      {
          CGRect bounds = [self bounds];
          CGContextRef context = UIGraphicsGetCurrentContext();
          CGContextClearRect(context, bounds);
      
          [[UIColor whiteColor] setFill];
          CGContextFillRect(context, bounds);
      
          CGRect aspectFitRect = [self aspectFit:self.image inFrame:bounds];
      
          if (self.image && self.enabled == NO) {
              [[UIColor grayColor] setFill];
              CGContextTranslateCTM(context, 0, bounds.size.height);
              CGContextScaleCTM(context, 1.0, -1.0);
      
              CGContextClipToMask(context, aspectFitRect, [self.image CGImage]);
              CGContextFillRect(context, bounds);        
          } else if (self.image) {
              [self.image drawInRect:aspectFitRect];
          }
      }
      
      
      -(CGRect)aspectFit:(UIImage*)image inFrame:(CGRect)outerFrame {
      
          CGSize imageSize = image.size;
          CGSize viewSize = outerFrame.size;
      
          float hfactor = imageSize.width / viewSize.width;
          float vfactor = imageSize.height / viewSize.height;
      
          float factor = fmax(hfactor, vfactor);
      
          // Divide the size by the greater of the vertical or horizontal shrinkage factor
          float newWidth = imageSize.width / factor;
          float newHeight = imageSize.height / factor;
          float newX = outerFrame.origin.x + (outerFrame.size.width - newWidth)/2;
          float newY = outerFrame.origin.y + (outerFrame.size.height - newHeight)/2;
      
          CGRect newRect = CGRectMake(newX, newY, newWidth, newHeight);
          return newRect;
      }
      
      @end
      

      【讨论】:

      • 可以使用 UIImageView 但需要将 contentMode 设置为 UIViewContentModeRedraw
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多