Создайте UIImage со сплошным цветом в Swift

146

Я хочу программно создать UIImage, заполненный сплошным цветом. Кто-нибудь знает, как это сделать в Swift?

Генри Фам
источник
UIImageнет -initWithSize:andColor:метода, но NSImageесть в OS X. Используете ли вы для этого специальную библиотеку или категорию?
ttarik
Извините, это правда, что я использовал его через категорию (глядя на старый проект). Просто отредактируйте мой вопрос.
Генри Фам,

Ответы:

202

Еще одно приятное решение - Swift 3.0

    public extension UIImage {
      public convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
        let rect = CGRect(origin: .zero, size: size)
        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
        color.setFill()
        UIRectFill(rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        guard let cgImage = image?.cgImage else { return nil }
        self.init(cgImage: cgImage)
      }
    }

Совместимость с Swift 2.2 заключается в создании другого конструктора в UIImage следующим образом:

    public extension UIImage {
        public convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
            let rect = CGRect(origin: .zero, size: size)
            UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
            color.setFill()
            UIRectFill(rect)
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
        
            guard let cgImage = image?.CGImage else { return nil }
            self.init(CGImage: cgImage)
        }  
    }

Таким образом, вы можете создать собственное цветное изображение следующим образом:

    let redImage = UIImage(color: .redColor())

Или, при желании, создайте изображение нестандартного размера:

    let redImage200x200 = UIImage(color: .redColor(), size: CGSize(width: 200, height: 200))
Лука Даванцо
источник
1
если вы хотите создать изображение с размером 1x, начните с этого кода UIGraphicsBeginImageContextWithOptions(rect.size, true, 1.0) ref: developer.apple.com/library/ios/documentation/UIKit/Reference/…
nahung89
3
Как сделать эти изображения более округлыми?
Умайр Афзал
Почему мы не можем просто вернуться image? Зачем это нужно делать? self.init(cgImage: cgImage)
Андрей Гаган
@AndreyGagan AFAIK, вы не можете "заменить" self вновь созданным UIImageв конструкторе, но UIImage.init(cgImage: )вместо этого вы можете создать цепочку через конструктор.
Alnitak
2
Изображение создано в неправильном масштабе. Например, если размер 1x1, изображение 2x2 возвращается, когда масштаб основного экрана равен 2,0. Вы должны позвонитьself.init(cgImage: cgImage, scale: image!.scale, orientation: image!.imageOrientation)
Мариан Черны
98

Версия Swift 4:

extension UIColor {
    func image(_ size: CGSize = CGSize(width: 1, height: 1)) -> UIImage {
        return UIGraphicsImageRenderer(size: size).image { rendererContext in
            self.setFill()
            rendererContext.fill(CGRect(origin: .zero, size: size))
        }
    }
}

Применение:

let image0 = UIColor.orange.image(CGSize(width: 128, height: 128))
let image1 = UIColor.yellow.image()
неоней
источник
3
Мне нравится, что созданный имидж не является необязательным
jlukanta
1
Мне это очень нравится, для меня имеет смысл использовать расширение на основе цвета, а не изображения.
quemeful
1
(⚠️ iOS 10 или новее). Кстати, хороший и чистый ответ.
fouo
92

Вот еще вариант. Я полагаю, вам нужен точный объект UIImage.

func getImageWithColor(color: UIColor, size: CGSize) -> UIImage {
    let rect = CGRectMake(0, 0, size.width, size.height)
    UIGraphicsBeginImageContextWithOptions(size, false, 0)
    color.setFill()
    UIRectFill(rect)
    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image
}

Вставьте это в свой код Swift и назовите

Swift 3.1:

func getImageWithColor(color: UIColor, size: CGSize) -> UIImage {
    let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
    UIGraphicsBeginImageContextWithOptions(size, false, 0)
    color.setFill()
    UIRectFill(rect)
    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    return image
}
Anthonyliao
источник
Я думаю , что нет никакого способа UIRectMake(0, 0, size.width, size.height), это кажется правильным: CGRectMake(0, 0, size.width, size.height).
Генри Фам,
1
Как правило, попробуйте использовать letвместо varнеизменяемых переменных; здесь похоже, что ни одно объявление rectне imageдолжно использоваться var.
Зорайр
1
Как сделать эти изображения более округлыми?
Умайр Афзал
19

Более чистый подход заключался бы в инкапсуляции логики внутри UIImageрасширения:

import UIKit

extension UIImage {
  class func imageWithColor(color: UIColor) -> UIImage {
    let rect: CGRect = CGRectMake(0, 0, 1, 1)
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(1, 1), false, 0)
    color.setFill()
    UIRectFill(rect)
    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image
  }
}

Теперь потребитель может позвонить, UIImage.imageWithColor(UIColor.blackColor())чтобы создать изображение с черным фоном.

Зорайр
источник
Как сделать эти изображения более округлыми?
Умайр Афзал
10
class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        imageView.backgroundColor = UIColor.redColor()
    }
}

Аналогичный метод, если вы хотите нарисовать изображение самостоятельно, вместо подключения через IBOutlet.

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var frame = CGRectMake(100,100,100,100)
        var imageView2 = UIImageView(frame: frame)
        imageView2.backgroundColor = UIColor.redColor()
        self.view.addSubview(imageView2)
    }
}

Третий метод заимствования из anthonyliao. Немного сложнее:

class ViewController: UIViewController {

    func getImageWithColor(color: UIColor, size: CGSize) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        color.setFill()
        UIRectFill(CGRectMake(0, 0, 100, 100))
        var image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        var imageView = UIImageView(frame: CGRectMake(100,100,100,100))
        let screenImage = getImageWithColor(UIColor.redColor(), size: CGSize(width: 100, height: 100))
        imageView.image = screenImage
        self.view.addSubview(imageView)
    }
}
Стив Розенберг
источник
2
Это, вероятно, обеспечивает эффект, который хотел OP, но ничего не стоит, что у них был метод для создания, а UIImageне для установки UIImageView.
ttarik
Ваш второй метод по-прежнему создает представление изображения, а не изображение, на что указывал @ ev0lution.
rdelmar
редактировать 3 прилагается. Теперь у нас есть несколько способов. Последний с UIImageView.
Стив Розенберг,
1
getImageWithColor(color: UIColor, size: CGSize) -> UIImageЭтого метода достаточно в качестве ответа, поскольку я думаю, что не все будут использовать его вместе с UIImageView
Генри Фам
Как сделать эти изображения более округлыми?
Умайр Афзал
9

Небольшая поправка к отличному ответу @neoneye, позволяющая вызывающему коду не создавать CGSize и измененная имя, чтобы не конфликтовать с множеством других:

Swift 4

extension UIColor {
    func imageWithColor(width: Int, height: Int) -> UIImage {
        let size = CGSize(width: width, height: height)
        return UIGraphicsImageRenderer(size: size).image { rendererContext in
            self.setFill()
            rendererContext.fill(CGRect(origin: .zero, size: size))
        }
    }
}
нарисовался..
источник
8

Вы можете использовать новый API iOS 10 UIGraphicsImageRenderer .

Вот расширение UIColor в Swift 3.1

extension UIColor {
func getImage(size: CGSize) -> UIImage {
    let renderer = UIGraphicsImageRenderer(size: size)
    return renderer.image(actions: { rendererContext in
        self.setFill()
        rendererContext.fill(CGRect(x: 0, y: 0, width: size.width, height: size.height))
    })
}}
Мустафа Баальбаки
источник
6

Хороший способ - иметь такое вычисленное свойство:

extension UIColor {
    var imageRepresentation : UIImage {
      let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
      UIGraphicsBeginImageContext(rect.size)
      let context = UIGraphicsGetCurrentContext()

      context?.setFillColor(self.cgColor)
      context?.fill(rect)

      let image = UIGraphicsGetImageFromCurrentImageContext()
      UIGraphicsEndImageContext()

    return image!
  }
}

Применение:

let redImage = UIColor.red.imageRepresentation
iOSGeek
источник
Я думаю, что некоторые ответы здесь немного вводят в заблуждение. В большинстве случаев вам нужно будет указать размер изображения, а не конкретный случай (например, 1x1). Но это хороший подход.
Генри Фам,
4

Swift 3 версия @anthonyliao Принятый ответ:

class func getImageWithColor(color: UIColor, size: CGSize) -> UIImage
{
    let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: size.width, height: size.height))
    UIGraphicsBeginImageContextWithOptions(size, false, 0)
    color.setFill()
    UIRectFill(rect)
    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    return image
}
Айман Ибрагим
источник
1

Прямоугольник с закругленными углами

extension UIImage {
convenience init?(color: UIColor) {
    let rect = CGRect(x: 0, y: 0, width: 10, height: 2)
    UIGraphicsBeginImageContextWithOptions(CGSize(width: 10, height: 2), false, 0)
    let bezierPath = UIBezierPath(roundedRect: rect, cornerRadius: 8)
    color.setFill()
    bezierPath.fill()
    let image = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()

    guard  let cgImage = image.cgImage else {
        return nil
    }
    self.init(cgImage: cgImage)
}

}

дроид
источник
0

мы можем использовать UIGraphicsImageRenderer для создания UIImage или использовать традиционный подход CGContext, ниже - удобная функция инициализации, которая создает UIImage с заданным цветом

extension UIImage {
    /// create UIImage with color and given size
    convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1), alpha: CGFloat = 1, scale: CGFloat = 0) {
        if #available(tvOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(size: size)
            let image = renderer.image { (ctx) in
                let size = renderer.format.bounds.size
                ctx.fill(CGRect(origin: .zero, size: size))
                ctx.cgContext.setFillColor(color.cgColor)
            }
            guard let cgImage = image.cgImage else { return nil }
            self.init(cgImage: cgImage)
        } else {
            let rect = CGRect(origin: .zero, size: size)
            UIGraphicsBeginImageContextWithOptions(rect.size, false, scale)
            let context = UIGraphicsGetCurrentContext()!
            let fillColor = color.withAlphaComponent(alpha)
            context.setFillColor(fillColor.cgColor)
            context.fill(rect)
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            guard let cgImage = image?.cgImage else { return nil }
            self.init(cgImage: cgImage)
        }
    }
}
Сухит Патил
источник