Crie UIImage com cores sólidas no Swift


140

Quero criar programaticamente uma UIImage preenchida por uma cor sólida. Alguém tem uma idéia de como fazer isso no Swift?


UIImagenão possui um -initWithSize:andColor:método, mas NSImagepossui no OS X. Você está usando uma biblioteca ou categoria personalizada para isso?
Ttarik 24/10/14

Desculpe, é verdade que eu o usei em uma categoria (olhando para um projeto antigo). Apenas edite minha pergunta.
Henry Pham

Respostas:


194

Outra solução interessante, compatível com Swift 2.2 , é criar outro construtor no UIImage, desta maneira:

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

Dessa maneira, você pode criar a imagem colorida personalizada da seguinte maneira:

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

Ou, opcionalmente, crie a imagem com um tamanho personalizado:

let redImage200x200 = UIImage(color: .redColor(), size: CGSize(width: 200, height: 200))

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

1
se você deseja criar uma imagem com tamanho 1x, comece com este código UIGraphicsBeginImageContextWithOptions(rect.size, true, 1.0) ref: developer.apple.com/library/ios/documentation/UIKit/Reference/…
nahung89

3
Como podemos tornar essas imagens mais arredondadas?
Umair Afzal

Por que não podemos simplesmente voltar image? Por que precisa fazer isso? self.init(cgImage: cgImage)
precisa saber é o seguinte

@AndreyGagan AFAIK, você não pode "substituir" o eu pelo recém-criado UIImageem um construtor, mas pode encadear através do UIImage.init(cgImage: )construtor.
Alnitak

2
A imagem não é criada com a escala adequada. Por exemplo, quando o tamanho é 1x1, uma imagem 2x2 é retornada quando a escala da tela principal é 2,0. Você deve ligarself.init(cgImage: cgImage, scale: image!.scale, orientation: image!.imageOrientation)
Marián Černý

92

Aqui está outra opção. Eu acredito que você queria um objeto UIImage exato.

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
}

Coloque isso no seu código Swift e chame-o

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
}

Eu acho que não há nenhum método UIRectMake(0, 0, size.width, size.height), este parece ser o correto: CGRectMake(0, 0, size.width, size.height).
Henry Pham

1
Geralmente, tente usar em letvez de varpara variáveis ​​imutáveis; aqui parece que rectnem imagedeveria estar usando vardeclaração.
Zorayr

1
Como podemos tornar essas imagens mais arredondadas?
Umair Afzal

83

Versão 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))
        }
    }
}

Uso:

let image0 = UIColor.orange.image(CGSize(width: 128, height: 128))
let image1 = UIColor.yellow.image()

3
Eu gosto que a imagem criada não seja opcional
jlukanta

1
Eu gosto muito disso, para mim faz muito sentido que a extensão seja da cor e não da imagem.
quemeful 12/07/19

1
(IOS️ iOS 10 ou mais recente). Resposta agradável e limpa entre.
Frouo 28/10/19

19

Uma abordagem mais limpa seria encapsular a lógica dentro de uma UIImageextensão:

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

Agora o consumidor pode ligar UIImage.imageWithColor(UIColor.blackColor())para criar uma imagem com fundo preto.


Como podemos tornar essas imagens mais arredondadas?
Umair Afzal

10
class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        imageView.backgroundColor = UIColor.redColor()
    }
}

Método semelhante, se você quiser desenhar a imagem, em vez de conectar uma via 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)
    }
}

Terceiro método emprestado de anthonyliao. Um pouco mais complicado:

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
Este , provavelmente, atinge o efeito que a OP queria, mas vale a pena nada que eles tinham um método para criar um UIImage, não para definir um UIImageView.
ttarik

Seu segundo método ainda cria uma visualização de imagem, não uma imagem, que é o que @ ev0lution estava apontando.
Rdelmar # 24/14

editar 3 anexado. Agora temos várias maneiras. Final com um UIImageView.
9788 Steve Rosenberg #

1
O método getImageWithColor(color: UIColor, size: CGSize) -> UIImageé o suficiente como a resposta, como eu acho que nem todo mundo vai usar isso em conjunto com um UIImageView
Henry Pham

Como podemos tornar essas imagens mais arredondadas?
Umair Afzal

9

Um pequeno ajuste na excelente resposta de @ neoneye, permitindo que o código de chamada não precise criar o CGSize e alterou o nome para não colidir com muitos outros:

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

Você pode usar a nova API do iOS 10 UIGraphicsImageRenderer .

Aqui está uma extensão no UIColor no 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

Uma boa maneira é ter uma propriedade computada como esta:

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

Uso:

let redImage = UIColor.red.imageRepresentation

Eu acho que algumas respostas aqui são um pouco enganadoras. Na maioria das vezes, você precisará especificar o tamanho da imagem, não um caso específico (como 1x1). Mas esta é uma boa abordagem.
Henry Pham

4

Versão Swift 3 de @anthonyliao Resposta aceita:

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
}

0

Reto com cantos arredondados

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

}

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.