Buat UIImage dengan warna solid di Swift

140

Saya ingin secara pemrograman membuat UIImage yang diisi oleh warna solid. Adakah yang tahu cara melakukan ini di Swift?

Henry Pham
sumber
UIImagetidak memiliki -initWithSize:andColor:metode, tetapi NSImagetidak pada OS X. Apakah Anda menggunakan perpustakaan khusus atau kategori untuk ini?
ttarik
Maaf, memang benar saya menggunakannya melalui kategori (melihat proyek lama). Cukup edit pertanyaan saya.
Henry Pham

Jawaban:

194

Solusi bagus lainnya, Swift 2.2 kompatibel, adalah membuat konstruktor lain di UIImage, dengan cara ini:

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

Dengan cara ini Anda dapat membuat gambar berwarna khusus dengan cara ini:

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

Atau, secara opsional, buat gambar dengan ukuran khusus:

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
sumber
1
jika Anda ingin membuat gambar dengan ukuran 1x, mulailah dengan kode ini UIGraphicsBeginImageContextWithOptions(rect.size, true, 1.0) ref: developer.apple.com/library/ios/documentation/UIKit/Reference/…
nahung89
3
Bagaimana kita bisa membuat sudut-sudut gambar ini lebih bulat?
Umair Afzal
Kenapa kita tidak bisa kembali begitu saja image? Mengapa perlu melakukan ini? self.init(cgImage: cgImage)
Andrey Gagan
@AndreyGagan AFAIK, Anda tidak dapat "mengganti" diri dengan yang baru dibuat UIImagedalam sebuah konstruktor, tetapi Anda dapat berantai melalui UIImage.init(cgImage: )konstruktor sebagai gantinya.
Alnitak
2
Gambar tidak dibuat dengan skala yang tepat. Misal ketika ukurannya 1x1, gambar 2x2 dikembalikan ketika skala layar utama 2.0. Anda harus meneleponself.init(cgImage: cgImage, scale: image!.scale, orientation: image!.imageOrientation)
Marián Černý
92

Ini pilihan lain. Saya yakin Anda menginginkan objek UIImage yang tepat.

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
}

Masukkan ini ke dalam kode Swift Anda dan panggil saja

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
sumber
Saya pikir tidak ada metode UIRectMake(0, 0, size.width, size.height), ini tampaknya menjadi yang benar: CGRectMake(0, 0, size.width, size.height).
Henry Pham
1
Secara umum, cobalah untuk menggunakan letalih-alih varuntuk variabel yang tidak dapat diubah; di sini sepertinya tidak rectjuga imageharus menggunakan vardeklarasi.
Zorayr
1
Bagaimana kita bisa membuat sudut-sudut gambar ini lebih bulat?
Umair Afzal
83

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

Pemakaian:

let image0 = UIColor.orange.image(CGSize(width: 128, height: 128))
let image1 = UIColor.yellow.image()
neoneye
sumber
3
Saya suka bahwa gambar yang dibuat bukan opsional
jlukanta
1
Saya sangat suka ini, bagi saya itu masuk akal untuk ekstensi dari warna daripada gambar.
quemeful
1
(⚠️ iOS 10 atau lebih baru). Bagus dan bersih, btw.
frouo
19

Pendekatan yang lebih bersih adalah merangkum logika di dalam UIImageekstensi:

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

Sekarang konsumen dapat menelepon, UIImage.imageWithColor(UIColor.blackColor())untuk membuat gambar dengan latar belakang hitam.

Zorayr
sumber
Bagaimana kita bisa membuat sudut-sudut gambar ini lebih bulat?
Umair Afzal
10
class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        imageView.backgroundColor = UIColor.redColor()
    }
}

Metode serupa jika Anda ingin menggambar gambar sendiri vs menghubungkan satu melalui 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)
    }
}

Metode ketiga meminjam dari anthonyliao. Sedikit lebih rumit:

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
sumber
2
Ini mungkin mencapai efek yang diinginkan OP tetapi tidak ada artinya bahwa mereka memiliki metode untuk membuat UIImage, bukan untuk menetapkan UIImageView.
ttarik
Metode kedua Anda masih membuat tampilan gambar, bukan gambar, yang ditunjukkan oleh @ ev0lution.
rdelmar
sunting 3 terlampir. Sekarang kita punya banyak cara. Final dengan UIImageView.
Steve Rosenberg
1
Metode getImageWithColor(color: UIColor, size: CGSize) -> UIImageini cukup sebagai jawabannya, karena saya pikir tidak semua orang akan menggunakan ini bersama-sama dengan UIImageView
Henry Pham
Bagaimana kita bisa membuat sudut-sudut gambar ini lebih bulat?
Umair Afzal
9

Tweak kecil untuk jawaban luar biasa @ neoneye, memungkinkan kode panggilan untuk tidak perlu membuat CGSize, dan mengubah nama agar tidak bertabrakan dengan banyak orang lain:

Cepat 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))
        }
    }
}
menggambar ..
sumber
8

Anda dapat menggunakan iOS 10 UIGraphicsImageRenderer API baru.

Berikut ini adalah ekstensi pada UIColor di 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
sumber
6

Cara yang bagus adalah memiliki properti yang dihitung seperti ini:

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

Pemakaian:

let redImage = UIColor.red.imageRepresentation
iOSGeek
sumber
Saya pikir beberapa jawaban di sini sedikit menyesatkan. Sebagian besar waktu Anda perlu menentukan ukuran gambar, bukan kasus tertentu (seperti 1x1). Tapi ini pendekatan yang bagus.
Henry Pham
4

Versi Swift 3 dari @anthonyliao Jawaban yang diterima:

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
sumber
0

Persegi dengan sudut bulat

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

}

droid
sumber