How to create a colored 1x1 UIImage on the iPhone dynamically?

38,277

Solution 1

You can use CGContextSetFillColorWithColor and CGContextFillRect for this:

Swift

extension UIImage {
    class func image(with color: UIColor) -> UIImage {
        let rect = CGRectMake(0.0, 0.0, 1.0, 1.0)
        UIGraphicsBeginImageContext(rect.size)
        let context = UIGraphicsGetCurrentContext()

        CGContextSetFillColorWithColor(context, color.CGColor)
        CGContextFillRect(context, rect)

        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return image
    }
}

Swift3

extension UIImage {
    class func image(with color: UIColor) -> UIImage {
        let rect = CGRect(origin: CGPoint(x: 0, y:0), size: CGSize(width: 1, height: 1))
        UIGraphicsBeginImageContext(rect.size)
        let context = UIGraphicsGetCurrentContext()!

        context.setFillColor(color.cgColor)
        context.fill(rect)

        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return image!
    }
}

Objective-C

+ (UIImage *)imageWithColor:(UIColor *)color {
    CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, rect);

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}

Solution 2

Here's another option based on Matt Stephen's code. It creates a resizable solid color image such that you could reuse it or change it's size (e.g. use it for a background).

+ (UIImage *)prefix_resizeableImageWithColor:(UIColor *)color {
    CGRect rect = CGRectMake(0.0f, 0.0f, 3.0f, 3.0f);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, rect);

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(1, 1, 1, 1)];

    return image;
}

Put it in a UIImage category and change the prefix.

Solution 3

I used Matt Steven's answer many times so made a category for it:

@interface UIImage (mxcl)
+ (UIImage *)squareImageWithColor:(UIColor *)color dimension:(int)dimension;
@end

@implementation UIImage (mxcl)
+ (UIImage *)squareImageWithColor:(UIColor *)color dimension:(int)dimension {
    CGRect rect = CGRectMake(0, 0, dimension, dimension);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextFillRect(context, rect);

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}
@end

Solution 4

Using Apple's latest UIGraphicsImageRenderer the code is pretty small:

import UIKit

extension UIImage {
    static func from(color: UIColor) -> UIImage {
        let size = CGSize(width: 1, height: 1)
        return UIGraphicsImageRenderer(size: size).image(actions: { (context) in
            context.cgContext.setFillColor(color.cgColor)
            context.fill(.init(origin: .zero, size: size))
        })
    }
}
Share:
38,277
Ian Terrell
Author by

Ian Terrell

Updated on May 22, 2020

Comments

  • Ian Terrell
    Ian Terrell almost 4 years

    I would like to create a 1x1 UIImage dynamically based on a UIColor.

    I suspect this can quickly be done with Quartz2d, and I'm poring over the documentation trying to get a grasp of the fundamentals. However, it looks like there are a lot of potential pitfalls: not identifying the numbers of bits and bytes per things correctly, not specifying the right flags, not releasing unused data, etc.

    How can this be safely done with Quartz 2d (or another simpler way)?

  • Admin
    Admin about 12 years
    Nice one :-) I would recommend putting this method into a category as a class method, then it can be added into a project simply, and invoked using a line like [UIImage imageWithColor: [UIColor redColor]].
  • hpique
    hpique about 10 years
    In case you're creating these images in a loop or using a bigger size, an optimisation would be to use an opaque canvas only if the color has alpha. Like this: const CGFloat alpha = CGColorGetAlpha(color.CGColor); const BOOL opaque = alpha == 1; UIGraphicsBeginImageContextWithOptions(size, opaque, 0);
  • fnc12
    fnc12 almost 9 years
    please provide swift version
  • Antzi
    Antzi almost 9 years
    Is there a way to make the swift one be a custom initializer instead ?
  • Iulian Onofrei
    Iulian Onofrei over 8 years
    Why is UIGraphicsGetCurrentContext() returnin nil? Edit: I got it, I was passing 0 for the rect's width.
  • Ian Newson
    Ian Newson over 7 years
    Added Swift 3 port
  • turingtested
    turingtested over 5 years
    @user577537 ...or in a catagory as an instance method of UIColor, so it would be even simpler [[UIColor redColor] image]