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?


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

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
}

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

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.


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

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

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

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

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
}

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

}}

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.