Crea UIImage con tinta unita in Swift


140

Voglio creare a livello di codice un UIImage riempito da un colore a tinta unita. Qualcuno ha un'idea di come farlo in Swift?


UIImagenon ha un -initWithSize:andColor:metodo, ma NSImagesu OS X. Stai usando una libreria o una categoria personalizzata per questo?
ttarik,

Siamo spiacenti, è vero che l'ho usato in una categoria (guardando un vecchio progetto). Modifica la mia domanda.
Henry Pham,

Risposte:


194

Un'altra bella soluzione, compatibile con Swift 2.2 , è quella di creare un altro costruttore in UIImage, in questo modo:

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

In questo modo è possibile creare l'immagine colorata personalizzata in questo modo:

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

Oppure, facoltativamente, crea l'immagine con una dimensione personalizzata:

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 si desidera creare un'immagine con dimensioni 1x, iniziare con questo codice UIGraphicsBeginImageContextWithOptions(rect.size, true, 1.0) ref: developer.apple.com/library/ios/documentation/UIKit/Reference/…
nahung89

3
Come possiamo rendere queste immagini più arrotondate?
Umair Afzal,

Perché non possiamo semplicemente tornare image? Perché è necessario farlo? self.init(cgImage: cgImage)
Andrey Gagan,

@AndreyGagan AFAIK, non puoi "rimpiazzare" il sé con il nuovo creato UIImagein un costruttore, ma puoi invece collegarlo tramite il UIImage.init(cgImage: )costruttore.
Alnitak,

2
L'immagine non viene creata con la scala corretta. Ad esempio, quando la dimensione è 1x1, viene restituita un'immagine 2x2 quando la scala dello schermo principale è 2.0. Dovresti chiamareself.init(cgImage: cgImage, scale: image!.scale, orientation: image!.imageOrientation)
Marián Černý il

92

Ecco un'altra opzione. Credo che tu volessi un oggetto UIImage esatto.

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
}

Inseriscilo nel tuo codice Swift e chiamalo

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
}

Credo che non esiste un metodo UIRectMake(0, 0, size.width, size.height), questo sembra essere quella corretta: CGRectMake(0, 0, size.width, size.height).
Henry Pham,

1
In generale, prova a utilizzare letinvece che varper variabili immutabili; qui sembra né rectimagedovrebbe essere utilizzando vardichiarazione.
Zorayr,

1
Come possiamo rendere queste immagini più arrotondate?
Umair Afzal,

84

Versione 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
Mi piace che l'immagine creata non sia un optional
jlukanta,

1
Mi piace molto, per me ha molto senso che l'estensione sia dal colore piuttosto che dall'immagine.
quemeful

1
(⚠️ iOS 10 o successivo). Bella e pulita risposta tra l'altro.
dal

19

Un approccio più pulito sarebbe quello di incapsulare la logica all'interno di UIImageun'estensione:

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

Ora il consumatore può chiamare UIImage.imageWithColor(UIColor.blackColor())per creare un'immagine con sfondo nero.


Come possiamo rendere queste immagini più arrotondate?
Umair Afzal,

10
class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        imageView.backgroundColor = UIColor.redColor()
    }
}

Metodo simile se si desidera disegnare l'immagine da soli anziché collegarne uno tramite 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)
    }
}

Terzo metodo preso in prestito da anthonyliao. Un po 'più complicato:

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
Questo probabilmente ottiene l'effetto desiderato da OP, ma non vale la pena avere un metodo per creare un UIImage, non per impostare un UIImageView.
ttarik,

Il tuo secondo metodo crea ancora una vista immagine, non un'immagine, che è ciò che @ ev0lution stava sottolineando.
rdelmar,

modifica 3 in allegato. Ora abbiamo un sacco di modi. Quello finale con UIImageView.
Steve Rosenberg,

1
Il metodo getImageWithColor(color: UIColor, size: CGSize) -> UIImageè sufficiente come risposta, poiché penso che non tutti lo useranno insieme a un UIImageView
Henry Pham,

Come possiamo rendere queste immagini più arrotondate?
Umair Afzal,

9

Una piccola modifica all'eccellente risposta di @ neoneye, che consente al codice chiamante di non dover creare CGSize e ha modificato il nome per non scontrarsi con numerosi altri:

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

Puoi usare il nuovo iOS 10 UIGraphicsImageRenderer API .

Ecco un'estensione su UIColor in 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

Un modo carino è avere una proprietà calcolata come questa:

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

Penso che alcune risposte qui siano un po 'fuorvianti. Il più delle volte dovrai specificare la dimensione dell'immagine, non un caso specifico (come 1x1). Ma questo è un buon approccio.
Henry Pham,

4

Swift 3 versione di @anthonyliao Risposta accettata:

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

Rettangolo con angoli arrotondati

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

}

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.