Làm thế nào để tạo một Hình ảnh 1x1 UII có màu trên iPhone một cách động?


120

Tôi muốn tạo một Hình ảnh UII1x1 động dựa trên UIColor.

Tôi nghi ngờ rằng điều này có thể nhanh chóng được thực hiện với Quartz2d và tôi đang nghiền ngẫm tài liệu để cố gắng nắm bắt các nguyên tắc cơ bản. Tuy nhiên, có vẻ như có rất nhiều cạm bẫy tiềm ẩn: không xác định chính xác số lượng bit và byte cho mỗi thứ, không chỉ định đúng cờ, không giải phóng dữ liệu không sử dụng, v.v.

Làm thế nào điều này có thể được thực hiện một cách an toàn với Quartz 2d (hoặc một cách khác đơn giản hơn)?

Câu trả lời:


331

Bạn có thể sử dụng CGContextSetFillColorWithColorCGContextFillRectcho điều này:

Nhanh

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
Cái hay :-) Tôi khuyên bạn nên đặt phương thức này vào một thể loại như một phương thức lớp, sau đó nó có thể được thêm vào một dự án một cách đơn giản và được gọi bằng cách sử dụng một dòng như thế [UIImage imageWithColor: [UIColor redColor]].

7
Trong trường hợp bạn đang tạo những hình ảnh này trong một vòng lặp hoặc sử dụng kích thước lớn hơn, cách tối ưu hóa sẽ là chỉ sử dụng canvas mờ nếu màu có alpha. Như thế này:const CGFloat alpha = CGColorGetAlpha(color.CGColor); const BOOL opaque = alpha == 1; UIGraphicsBeginImageContextWithOptions(size, opaque, 0);
hpique

vui lòng cung cấp nhanh chóng phiên bản
fnc12

Có cách nào để làm cho một cái nhanh chóng trở thành một bộ khởi tạo tùy chỉnh thay thế không?
Antzi

1
Tại sao lại là người UIGraphicsGetCurrentContext()trở lại nil? Chỉnh sửa : Tôi hiểu rồi, tôi đã vượt qua 0cho rectcủa width.
Iulian Onofrei

9

Đây là một tùy chọn khác dựa trên mã của Matt Stephen. Nó tạo ra một hình ảnh màu rắn có thể thay đổi kích thước để bạn có thể sử dụng lại nó hoặc thay đổi kích thước của nó (ví dụ: sử dụng nó làm nề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;
}

Đặt nó trong một danh mục Hình ảnh và thay đổi tiền tố.


6

Tôi đã sử dụng câu trả lời của Matt Steven nhiều lần nên đã tạo một danh mục cho nó:

@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

Sử dụng UIGraphicsImageRenderer mới nhất của Apple, mã khá nhỏ:

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

Đối với tôi, một init tiện lợi cảm thấy gọn gàng hơn trong 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)
    }

}

-7

Ok, đây sẽ không phải là chính xác những gì bạn muốn, nhưng mã này sẽ vẽ một đường thẳng. Bạn có thể điều chỉnh nó để tạo ra một quan điểm. Hoặc ít nhất có được một chút thông tin từ nó.

Tạo hình ảnh 1x1 có vẻ hơi kỳ lạ. Các nét vẽ đi theo đường thẳng, vì vậy hành trình có chiều rộng 1,0 ở 0,5 sẽ hoạt động. Chỉ chơi xung quanh.

- (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();
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.