İPhone'da dinamik olarak renkli 1x1 UIImage nasıl oluşturulur?


120

Bir UIColor'a dayalı olarak dinamik olarak 1x1 UIImage oluşturmak istiyorum.

Bunun Quartz2d ile hızlı bir şekilde yapılabileceğinden şüpheleniyorum ve temelleri kavramaya çalışırken belgeleri inceliyorum. Bununla birlikte, pek çok potansiyel tuzak var gibi görünüyor: her şey için bit ve bayt sayılarını doğru şekilde tanımlamamak, doğru bayrakları belirtmemek, kullanılmayan verileri serbest bırakmamak, vb.

Bu, Quartz 2d (veya daha basit bir yolla) ile nasıl güvenli bir şekilde yapılabilir?

Yanıtlar:


331

Bunun için CGContextSetFillColorWithColorve kullanabilirsiniz CGContextFillRect:

hızlı

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

19
Güzel bir :-) Bu yöntemi bir sınıf yöntemi olarak bir kategoriye koymanızı öneririm, daha sonra bir projeye basitçe eklenebilir ve gibi bir satır kullanılarak çağrılabilir [UIImage imageWithColor: [UIColor redColor]].

7
Bu görüntüleri bir döngüde oluşturuyorsanız veya daha büyük bir boyut kullanıyorsanız, yalnızca rengin alfa içermesi durumunda opak bir tuval kullanmak bir optimizasyon olacaktır. Bunun gibi:const CGFloat alpha = CGColorGetAlpha(color.CGColor); const BOOL opaque = alpha == 1; UIGraphicsBeginImageContextWithOptions(size, opaque, 0);
hpique

lütfen hızlı sürümü sağlayın
fnc12

Hızlı olanı bunun yerine özel bir başlatıcı yapmanın bir yolu var mı?
Antzi

1
Neden UIGraphicsGetCurrentContext()geri dönüyor nil? Düzenleme : Anladım 0, rect'ler için geçiyordum width.
Iulian Onofrei

9

İşte Matt Stephen'ın koduna dayalı başka bir seçenek. Yeniden kullanabileceğiniz veya boyutunu değiştirebileceğiniz şekilde yeniden boyutlandırılabilir düz renkli bir görüntü oluşturur (örn. Arka plan için kullanın).

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

Bir UIImage kategorisine yerleştirin ve öneki değiştirin.


6

Matt Steven'ın cevabını birçok kez kullandım, bu yüzden bunun için bir kategori oluşturdum:

@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

Apple'ın en son UIGraphicsImageRenderer'ını kullanarak kod oldukça küçük:

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

Bana göre, bir kolaylık init, Swift'de daha düzenli hissediyor.

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

Tamam, bu tam olarak istediğin gibi olmayacak ama bu kod bir çizgi çizecek. Bir noktaya değinmek için onu uyarlayabilirsiniz. Ya da en azından ondan biraz bilgi alın.

Görüntüyü 1x1 yapmak biraz tuhaf görünüyor. Vuruşlar çizgiye biner, bu nedenle 0,5'te 1,0 genişliğinde bir vuruş çalışmalıdır. Sadece oynayın.

- (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();
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.