I have some colored icons with transparent backgrounds. I would like to automatically be able to show flat versions of those (solid color gray) depending on the state of the program.

Could I do this with Core Image filters? Is there another way?

有帮助吗?

解决方案 2

I think I've did same thing before, I have some colored icon, but I needs to keep the shape and change the color to a mono color. So I write an extension to UIImage.

Here is code, hope this help you.

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

其他提示

Subclass and make your own UIImageView (or UIView with a UIImageView property) and override drawRect, you will want to clip the context to an image mask and then fill with a solid colour:

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

Here's a UIView subclass I created. Many thanks to Oliver for pointing this out. I thought you couldn't subclass UIImageView at the time.

@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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top