Як динамічно створити кольоровий 1x1 UIImage на iPhone?


120

Я хотів би створити 1x1 UIImage динамічно на основі UIColor.

Я підозрюю, що це можна швидко зробити з Quartz2d, ​​і я переглядаю документацію, намагаючись зрозуміти основи. Однак, схоже, існує багато можливих підводних каменів: неправильне визначення кількості бітів і байтів на речі, не вказане правильних прапорів, не випущення невикористаних даних тощо.

Як це можна безпечно зробити за допомогою Quartz 2d (або іншим більш простим способом)?

Відповіді:


331

Ви можете використовувати CGContextSetFillColorWithColorі CGContextFillRectдля цього:

Швидкий

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

Швидкий3

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

Ціль-С

+ (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
Хороший :-) Я рекомендував би ввести цей метод у категорію як метод класу, тоді він може бути доданий до проекту просто та викликаний за допомогою рядка типу [UIImage imageWithColor: [UIColor redColor]].

7
У випадку, якщо ви створюєте ці зображення в циклі або використовуєте більший розмір, оптимізацією було б використання непрозорого полотна, лише якщо в кольорі є альфа. const CGFloat alpha = CGColorGetAlpha(color.CGColor); const BOOL opaque = alpha == 1; UIGraphicsBeginImageContextWithOptions(size, opaque, 0);
Ось так

надайте швидку версію
fnc12,

Чи є спосіб зробити так, щоб швидкий був замість нього власним ініціалізатором?
Antzi

1
Чому UIGraphicsGetCurrentContext()повернення nil? Редагувати : я це отримав, я проходив 0за rect's width.
Юліан Онофрей

9

Ось ще один варіант, заснований на коді Метта Стівена. Це створює змінне зміна суцільного кольору таким чином, щоб ви могли повторно використовувати його або змінити його розмір (наприклад, використовувати його для фону).

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

Помістіть його в категорію UIImage та змініть префікс.


6

Я багато разів використовував відповідь Метта Стівена, тому робив для неї категорію:

@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

Використовуючи останній UIGraphicsImageRenderer від Apple, код досить малий:

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

Для мене зручність init відчуває себе акуратніше у Свіфті.

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

Гаразд, це не буде саме те, що ви хочете, але цей код буде проводити лінію. Ви можете адаптувати його, щоб зробити точку. Або хоча б отримати з нього трохи інформації.

Зробити зображення 1x1 здається трохи дивним. Штрихи їздять по лінії, тому хід шириною 1,0 на 0,5 повинен працювати. Просто пограйте.

- (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();
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.