Bagaimana cara membuat gambar UII 1x1 berwarna pada iPhone secara dinamis?

120

Saya ingin membuat gambar UII 1x1 secara dinamis berdasarkan UIColor.

Saya menduga ini dapat dengan cepat dilakukan dengan Quartz2d, ​​dan saya mempelajari dokumentasi mencoba untuk memahami fundamentalnya. Namun, sepertinya ada banyak potensi jebakan: tidak mengidentifikasi jumlah bit dan byte per hal dengan benar, tidak menentukan flag yang tepat, tidak merilis data yang tidak digunakan, dll.

Bagaimana ini bisa dilakukan dengan aman dengan Quartz 2d (atau cara lain yang lebih sederhana)?

Ian Terrell
sumber

Jawaban:

331

Anda dapat menggunakan CGContextSetFillColorWithColordan CGContextFillRectuntuk ini:

Cepat

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;
}
Matt Stevens
sumber
19
Bagus :-) Saya akan merekomendasikan untuk memasukkan metode ini ke dalam kategori sebagai metode kelas, kemudian dapat ditambahkan ke dalam proyek secara sederhana, dan dipanggil menggunakan baris seperti [UIImage imageWithColor: [UIColor redColor]].
7
Jika Anda membuat gambar ini dalam satu lingkaran atau menggunakan ukuran yang lebih besar, pengoptimalannya adalah menggunakan kanvas buram hanya jika warnanya memiliki alfa. Seperti ini:const CGFloat alpha = CGColorGetAlpha(color.CGColor); const BOOL opaque = alpha == 1; UIGraphicsBeginImageContextWithOptions(size, opaque, 0);
hpique
berikan versi cepat
fnc12
Adakah cara untuk menjadikan swift sebagai penginisialisasi khusus?
Antzi
1
Mengapa UIGraphicsGetCurrentContext()kembali nil? Sunting : Saya mengerti, saya lulus 0untuk rectitu width.
Iulian Onofrei
9

Berikut opsi lain berdasarkan kode Matt Stephen. Ini menciptakan gambar warna solid yang dapat diubah ukurannya sehingga Anda dapat menggunakannya kembali atau mengubah ukurannya (misalnya menggunakannya untuk latar belakang).

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

Taruh di kategori UIImage dan ubah awalannya.

Ben Lachman
sumber
6

Saya menggunakan jawaban Matt Steven berkali-kali sehingga membuat kategori untuk itu:

@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
mxcl
sumber
5

Menggunakan UIGraphicsImageRenderer terbaru dari Apple, kodenya cukup kecil:

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))
        })
    }
}
bitwit
sumber
0

Bagi saya, kenyamanan di dalamnya terasa lebih rapi di Swift.

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

}
Mark Bridges
sumber
-7

Oke, ini tidak akan persis seperti yang Anda inginkan, tetapi kode ini akan menarik garis. Anda dapat mengadaptasinya untuk membuat suatu poin. Atau setidaknya dapatkan sedikit info darinya.

Membuat gambar 1x1 tampak agak aneh. Pukulan naik pada garis, jadi guratan dengan lebar 1,0 pada 0,5 seharusnya berhasil. Main-main saja.

- (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();
}
Corey Floyd
sumber