Erstellen Sie UIImage mit Volltonfarben in Swift

140

Ich möchte programmgesteuert ein UIImage erstellen, das mit einer Volltonfarbe gefüllt ist. Hat jemand eine Idee, wie man das in Swift macht?

Henry Pham
quelle
UIImagehat keine -initWithSize:andColor:Methode, aber NSImageunter OS X. Verwenden Sie hierfür eine benutzerdefinierte Bibliothek oder Kategorie?
Ttarik
Entschuldigung, es ist wahr, dass ich es in einer Kategorie verwendet habe (mit Blick auf ein altes Projekt). Bearbeiten Sie einfach meine Frage.
Henry Pham

Antworten:

194

Eine andere nette Lösung, Swift 2.2- kompatibel, besteht darin, einen anderen Konstruktor in UIImage auf folgende Weise zu erstellen:

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

Auf diese Weise können Sie das benutzerdefinierte Farbbild folgendermaßen erstellen:

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

Oder erstellen Sie optional das Bild mit einer benutzerdefinierten Größe:

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)
  }
}
Luca Davanzo
quelle
1
Wenn Sie ein Bild mit einer Größe von 1x erstellen möchten, beginnen Sie mit dem folgenden Code UIGraphicsBeginImageContextWithOptions(rect.size, true, 1.0) : developer.apple.com/library/ios/documentation/UIKit/Reference/…
nahung89
3
Wie können wir diese Bilder runder machen?
Umair Afzal
Warum können wir nicht einfach zurückkehren image? Warum müssen Sie das tun? self.init(cgImage: cgImage)
Andrey Gagan
@AndreyGagan AFAIK, Sie können sich nicht durch das neu erstellte UIImagein einem Konstruktor "ersetzen" , aber Sie können über das verkettenUIImage.init(cgImage: ) stattdessen Konstruktor verketten.
Alnitak
2
Das Bild wird nicht mit dem richtigen Maßstab erstellt. Wenn beispielsweise die Größe 1x1 beträgt, wird ein Bild 2x2 zurückgegeben, wenn der Hauptbildschirm 2,0 beträgt. Sie sollten anrufenself.init(cgImage: cgImage, scale: image!.scale, orientation: image!.imageOrientation)
Marián Černý
92

Hier ist eine weitere Option. Ich glaube, Sie wollten ein genaues UIImage-Objekt.

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
}

Schreiben Sie dies in Ihren Swift-Code und nennen Sie es

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
quelle
Ich denke, es gibt keine Methode UIRectMake(0, 0, size.width, size.height), dies scheint die richtige zu sein : CGRectMake(0, 0, size.width, size.height).
Henry Pham
1
Versuchen Sie im Allgemeinen, letanstelle von varunveränderlichen Variablen zu verwenden. hier scheint weder rectnoch imagesollte varDeklaration verwendet werden.
Zorayr
1
Wie können wir diese Bilder runder machen?
Umair Afzal
83

Swift 4 Version:

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

Verwendung:

let image0 = UIColor.orange.image(CGSize(width: 128, height: 128))
let image1 = UIColor.yellow.image()
neoneye
quelle
3
Ich mag, dass das erstellte Bild nicht optional ist
jlukanta
1
Ich mag das sehr, für mich ist es sehr sinnvoll, dass die Erweiterung eher aus Farbe als aus Bild besteht.
quemeful
1
(⚠️ iOS 10 oder neuer). Schöne und saubere Antwort übrigens.
Frouo
19

Ein sauberer Ansatz wäre, die Logik in einer UIImageErweiterung zu kapseln :

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

Jetzt kann der Verbraucher anrufen, UIImage.imageWithColor(UIColor.blackColor())um ein Bild mit schwarzem Hintergrund zu erstellen.

Zorayr
quelle
Wie können wir diese Bilder runder machen?
Umair Afzal
10
class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        imageView.backgroundColor = UIColor.redColor()
    }
}

Ähnliche Methode, wenn Sie das Bild selbst zeichnen möchten, anstatt eines über IBOutlet zu verbinden.

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

Dritte Methode aus Anthonyliao entlehnt. Etwas komplizierter:

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)
    }
}
Steve Rosenberg
quelle
2
Dies erreicht wahrscheinlich den Effekt, den OP wollte, aber es ist nichts wert, dass sie eine Methode hatten, um eine zu erstellen UIImage, nicht um eine zu setzen UIImageView.
Ttarik
Ihre zweite Methode erstellt immer noch eine Bildansicht, kein Bild, worauf @ ev0lution hingewiesen hat.
Rdelmar
bearbeiten 3 beigefügt. Jetzt haben wir eine Reihe von Möglichkeiten. Letzte mit einem UIImageView.
Steve Rosenberg
1
Die Methode getImageWithColor(color: UIColor, size: CGSize) -> UIImageist genug als Antwort, da ich denke, dass nicht jeder dies zusammen mit einem UIImageView
Henry Pham
Wie können wir diese Bilder runder machen?
Umair Afzal
9

Eine kleine Änderung an der hervorragenden Antwort von @ neoneye, die es dem aufrufenden Code ermöglicht, die CGSize nicht erstellen zu müssen, und der Name wurde geändert, um nicht mit zahlreichen anderen zu kollidieren:

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))
        }
    }
}
zeichnete ..
quelle
8

Sie können den neuen iOS 10 UIGraphicsImageRenderer verwenden API verwenden.

Hier ist eine Erweiterung von 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))
    })
}}
Moustafa Baalbaki
quelle
6

Ein guter Weg ist, eine berechnete Eigenschaft wie diese zu haben:

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

Verwendung:

let redImage = UIColor.red.imageRepresentation
iOSGeek
quelle
Ich denke, einige Antworten hier sind etwas irreführend. Meistens müssen Sie die Größe des Bildes angeben, nicht einen bestimmten Fall (wie 1x1). Aber das ist ein schöner Ansatz.
Henry Pham
4

Swift 3-Version von @anthonyliao Akzeptierte Antwort:

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
}
Ayman Ibrahim
quelle
0

Rect mit abgerundeten Ecken

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

}}

Droide
quelle