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é rectné imagedovrebbe 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.