Wie erstelle ich dynamisch ein farbiges 1x1 UIImage auf dem iPhone?


120

Ich möchte ein 1x1 UIImage dynamisch basierend auf einer UIColor erstellen.

Ich vermute, dass dies mit Quartz2d schnell erledigt werden kann, und ich stöbere in der Dokumentation, um die Grundlagen zu verstehen. Es sieht jedoch so aus, als gäbe es viele potenzielle Fallstricke: die Anzahl der Bits und Bytes pro Sache nicht richtig zu identifizieren, die richtigen Flags nicht anzugeben, nicht verwendete Daten nicht freizugeben usw.

Wie kann dies sicher mit Quartz 2d (oder einem anderen einfacheren Weg) gemacht werden?

Antworten:


331

Sie können CGContextSetFillColorWithColorund CGContextFillRectdafür verwenden:

Schnell

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!
    }
}

Ziel 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;
}

19
Schön :-) Ich würde empfehlen, diese Methode als Klassenmethode in eine Kategorie einzufügen. Dann kann sie einfach in ein Projekt eingefügt und mit einer Zeile wie aufgerufen werden [UIImage imageWithColor: [UIColor redColor]].

7
Wenn Sie diese Bilder in einer Schleife erstellen oder eine größere Größe verwenden, besteht eine Optimierung darin, eine undurchsichtige Leinwand nur dann zu verwenden, wenn die Farbe Alpha enthält. So:const CGFloat alpha = CGColorGetAlpha(color.CGColor); const BOOL opaque = alpha == 1; UIGraphicsBeginImageContextWithOptions(size, opaque, 0);
hpique

Bitte geben Sie eine schnelle Version an
fnc12

Gibt es eine Möglichkeit, den schnellen stattdessen zu einem benutzerdefinierten Initialisierer zu machen?
Antzi

1
Warum UIGraphicsGetCurrentContext()kehrt ich zurück nil? Bearbeiten : Ich habe es, ich war vorbei 0für die rect‚s width.
Iulian Onofrei

9

Hier ist eine weitere Option, die auf dem Code von Matt Stephen basiert. Es wird ein anpassbares Vollfarbbild erstellt, sodass Sie es wiederverwenden oder seine Größe ändern können (z. B. als Hintergrund verwenden).

+ (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;
}

Fügen Sie es in eine UIImage-Kategorie ein und ändern Sie das Präfix.


6

Ich habe die Antwort von Matt Steven viele Male verwendet, also habe ich eine Kategorie dafür erstellt:

@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

5

Mit Apples neuestem UIGraphicsImageRenderer ist der Code ziemlich klein:

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))
        })
    }
}

0

Für mich fühlt sich ein Convenience-Init in Swift ordentlicher an.

extension UIImage {

    convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {

        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        UIGraphicsBeginImageContext(rect.size)
        guard let context = UIGraphicsGetCurrentContext() else {
            return nil
        }

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

        guard let image = context.makeImage() else {
            return nil
        }
        UIGraphicsEndImageContext()

        self.init(cgImage: image)
    }

}

-7

Ok, das wird nicht genau das sein, was Sie wollen, aber dieser Code wird eine Linie ziehen. Sie können es anpassen, um einen Punkt zu machen. Oder zumindest ein paar Infos davon.

Das Bild 1x1 zu machen scheint etwas seltsam. Striche fahren auf der Linie, daher sollte ein Strich mit einer Breite von 1,0 bei 0,5 funktionieren. Spielen Sie einfach herum.

- (void)drawLine{

UIGraphicsBeginImageContext(CGSizeMake(320,300));

CGContextRef ctx = UIGraphicsGetCurrentContext();

float x = 0;
float xEnd = 320;
float y = 300;

CGContextClearRect(ctx, CGRectMake(5, 45, 320, 300));

CGContextSetGrayStrokeColor(ctx, 1.0, 1.0);

CGContextSetLineWidth(ctx, 1);
CGPoint line[2] = { CGPointMake(x,y), CGPointMake(xEnd, y) };

CGContextStrokeLineSegments(ctx, line, 2);

UIImage *theImage=UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.