Ubah UIImage ke NSData dan ubah kembali ke UIImage di Swift?

147

Saya mencoba untuk menyimpan UIImageke NSDatadan kemudian membaca NSDatakembali ke yang baru UIImagedi Swift. Untuk mengonversi UIImagemenjadi NSDataSaya menggunakan kode berikut:

let imageData: NSData = UIImagePNGRepresentation(myImage)

Bagaimana cara mengonversi imageData(yaitu NSData) kembali ke yang baru UIImage?

pete
sumber

Jawaban:

164

UIImage(data:imageData,scale:1.0) dengan asumsi skala gambar adalah 1.

Dalam 4.2 cepat, gunakan kode di bawah ini untuk get Data ().

image.pngData()
alga
sumber
67

Terima kasih. Banyak membantu saya. Dikonversi ke Swift 3 dan bekerja

Untuk menyimpan: let data = UIImagePNGRepresentation(image)

Untuk memuat: let image = UIImage(data: data)

Ivan Sinigaglia
sumber
1
Apakah tidak let imagePt = UIImage(data: caminhodaImagem)cukup?
superarts.org
33

Gunakan imageWithData:metode, yang diterjemahkan ke Swift sebagaiUIImage(data:)

let image : UIImage = UIImage(data: imageData)
Sergey Kalinichenko
sumber
17

Sekarang di Swift 4.2 Anda dapat menggunakan pngData()metode contoh baru UIImageuntuk mendapatkan data dari gambar

let profileImage = UIImage(named:"profile")!
let imageData = profileImage.pngData()
Sh_Khan
sumber
Apakah Swift 4.2 dalam Beta? Saya tidak melihat fungsi ini tersedia
Daniel Springer
sepertinya sudah diganti namanya
吖 奇 说 の archywillhe
'pngData ()' telah diubah namanya menjadi 'UIImagePNGRepresentation (_ :)'
j2abro
10

Detail

  • Xcode 10.2.1 (10E1001), Swift 5

Solusi 1

guard let image = UIImage(named: "img") else { return }
let jpegData = image.jpegData(compressionQuality: 1.0)
let pngData = image.pngData()

Solusi 2.1

extension UIImage {
    func toData (options: NSDictionary, type: CFString) -> Data? {
        guard let cgImage = cgImage else { return nil }
        return autoreleasepool { () -> Data? in
            let data = NSMutableData()
            guard let imageDestination = CGImageDestinationCreateWithData(data as CFMutableData, type, 1, nil) else { return nil }
            CGImageDestinationAddImage(imageDestination, cgImage, options)
            CGImageDestinationFinalize(imageDestination)
            return data as Data
        }
    }
}

Penggunaan solusi 2.1

// about properties: https://developer.apple.com/documentation/imageio/1464962-cgimagedestinationaddimage
let options: NSDictionary =     [
    kCGImagePropertyOrientation: 6,
    kCGImagePropertyHasAlpha: true,
    kCGImageDestinationLossyCompressionQuality: 0.5
]

// https://developer.apple.com/documentation/mobilecoreservices/uttype/uti_image_content_types
guard let data = image.toData(options: options, type: kUTTypeJPEG) else { return }
let size = CGFloat(data.count)/1000.0/1024.0
print("\(size) mb")

Solusi 2.2

extension UIImage {

    func toJpegData (compressionQuality: CGFloat, hasAlpha: Bool = true, orientation: Int = 6) -> Data? {
        guard cgImage != nil else { return nil }
        let options: NSDictionary =     [
                                            kCGImagePropertyOrientation: orientation,
                                            kCGImagePropertyHasAlpha: hasAlpha,
                                            kCGImageDestinationLossyCompressionQuality: compressionQuality
                                        ]
        return toData(options: options, type: .jpeg)
    }

    func toData (options: NSDictionary, type: ImageType) -> Data? {
        guard cgImage != nil else { return nil }
        return toData(options: options, type: type.value)
    }
    // about properties: https://developer.apple.com/documentation/imageio/1464962-cgimagedestinationaddimage
    func toData (options: NSDictionary, type: CFString) -> Data? {
        guard let cgImage = cgImage else { return nil }
        return autoreleasepool { () -> Data? in
            let data = NSMutableData()
            guard let imageDestination = CGImageDestinationCreateWithData(data as CFMutableData, type, 1, nil) else { return nil }
            CGImageDestinationAddImage(imageDestination, cgImage, options)
            CGImageDestinationFinalize(imageDestination)
            return data as Data
        }
    }

    // https://developer.apple.com/documentation/mobilecoreservices/uttype/uti_image_content_types
    enum ImageType {
        case image // abstract image data
        case jpeg                       // JPEG image
        case jpeg2000                   // JPEG-2000 image
        case tiff                       // TIFF image
        case pict                       // Quickdraw PICT format
        case gif                        // GIF image
        case png                        // PNG image
        case quickTimeImage             // QuickTime image format (OSType 'qtif')
        case appleICNS                  // Apple icon data
        case bmp                        // Windows bitmap
        case ico                        // Windows icon data
        case rawImage                   // base type for raw image data (.raw)
        case scalableVectorGraphics     // SVG image
        case livePhoto                  // Live Photo

        var value: CFString {
            switch self {
            case .image: return kUTTypeImage
            case .jpeg: return kUTTypeJPEG
            case .jpeg2000: return kUTTypeJPEG2000
            case .tiff: return kUTTypeTIFF
            case .pict: return kUTTypePICT
            case .gif: return kUTTypeGIF
            case .png: return kUTTypePNG
            case .quickTimeImage: return kUTTypeQuickTimeImage
            case .appleICNS: return kUTTypeAppleICNS
            case .bmp: return kUTTypeBMP
            case .ico: return kUTTypeICO
            case .rawImage: return kUTTypeRawImage
            case .scalableVectorGraphics: return kUTTypeScalableVectorGraphics
            case .livePhoto: return kUTTypeLivePhoto
            }
        }
    }
}

Penggunaan solusi 2.2

let compressionQuality: CGFloat = 0.4
guard let data = image.toJpegData(compressionQuality: compressionQuality) else { return }
printSize(of: data)

let options: NSDictionary =     [
                                    kCGImagePropertyHasAlpha: true,
                                    kCGImageDestinationLossyCompressionQuality: compressionQuality
                                ]
guard let data2 = image.toData(options: options, type: .png) else { return }
printSize(of: data2)

Masalah

Representasi gambar akan membutuhkan banyak cpu dan sumber daya memori. Jadi, dalam hal ini lebih baik mengikuti beberapa aturan:

- jangan jalankan jpegData (compressionQuality :) pada antrian utama

- jalankan hanya satu jpegData (compressionQuality :) secara bersamaan

Salah:

for i in 0...50 {
    DispatchQueue.global(qos: .utility).async {
        let quality = 0.02 * CGFloat(i)
        //let data = image.toJpegData(compressionQuality: quality)
        let data = image.jpegData(compressionQuality: quality)
        let size = CGFloat(data!.count)/1000.0/1024.0
        print("\(i), quality: \(quality), \(size.rounded()) mb")
    }
}

Baik:

let serialQueue = DispatchQueue(label: "queue", qos: .utility, attributes: [], autoreleaseFrequency: .workItem, target: nil)

for i in 0...50 {
    serialQueue.async {
        let quality = 0.02 * CGFloat(i)
        //let data = image.toJpegData(compressionQuality: quality)
        let data = image.jpegData(compressionQuality: quality)
        let size = CGFloat(data!.count)/1000.0/1024.0
        print("\(i), quality: \(quality), \(size.rounded()) mb")
    }
}

Tautan

Bodnarchuk dengan mudah
sumber
Dengan mudah, ini sangat membantu. Saya dapat mengubah UIImages ke bmps menggunakan kode Anda. Saya juga perlu menghapus alpha dari bmp. Saya sudah mencoba mengatur opsi untuk menghapus alfa & sepertinya tidak bisa menyingkirkannya untuk menghilangkan lapisan. Saya menelepon seperti ini: biarkan opsi: NSDictionary = [kCGImagePropertyHasAlpha: false] biarkan convertToBmp = image.toData (opsi: opsi, ketik: .bmp)
Gallaugher
@Gallaugher apakah Anda yakin itu tidak berfungsi? Coba buat gambar png tanpa alpha dan periksa. Mungkin tidak mungkin menggunakan properti kCGImagePropertyHasAlpha dengan bmp.
Vasily Bodnarchuk
@ vasily-bodnarchuk Terima kasih atas petunjuknya (dan kode sebelumnya). Saya menyingkirkan alpha - saya tidak dapat melakukannya melalui png, tetapi saya menggunakan resizedImage.toJpegData dengan alpha sebagai false, lalu mengubah data ini kembali menjadi UIImage, lalu melakukan toData dengan tipe .bmp. Opsi tidak berdampak, tetapi lapisan alfa dihapus di Photoshop & membuat file yang lebih kecil. Masih tidak dapat menghasilkan format bmp grafis raster 16-bit yang tepat yang saya butuhkan untuk PyPortal. Untuk beberapa alasan, data yang diinginkan tidak ditampilkan oleh saat saya mengonversi melalui alat seperti konversi online. Terima kasih.
Gallaugher
@ vasily-bodnarchuk, bmp yang telah saya simpan menggunakan kode bermanfaat Anda terbuka di Photoshop dengan opsi bmp "Flip row order". Jika saya menyimpan ulang & menghapus centang opsi ini pada layar "Opsi BMP" yang muncul setelah "Simpan sebagai ...", lalu muat bmp pada acara bmp PyPortal yang diperbarui. Saya tidak melihat dokumen Apple yang tampak seperti opsi "Balik urutan baris", saya tidak yakin mengapa ini muncul sebagai penyimpanan default & saya tidak yakin bagaimana cara "membatalkan" ini di Swift. BTW: Saya telah memposting Q & file terkait di: stackoverflow.com/questions/57241391/… Terima kasih!
Gallaugher
8

Untuk menyimpan sebagai data:

Dari StoryBoard, jika Anda ingin menyimpan data "gambar" pada imageView dari MainStoryBoard, kode berikut akan berfungsi.

let image = UIImagePNGRepresentation(imageView.image!) as NSData?

Untuk memuat "image" ke imageView: Lihat tanda seru "!", "?" apakah itu sama dengan yang satu ini.

imageView.image = UIImage(data: image as! Data)

Jenis "NSData" diubah menjadi jenis "Data" secara otomatis selama proses ini.

zemunkh
sumber
6

Untuk eksekusi kode yang aman, gunakan if-letblock with Datauntuk mencegah aplikasi crash &, karena fungsi UIImagePNGRepresentationmengembalikan nilai opsional.

if let img = UIImage(named: "TestImage.png") {
    if let data:Data = UIImagePNGRepresentation(img) {
       // Handle operations with data here...         
    }
}

Catatan: Data adalah kelas Swift 3+. Gunakan Data sebagai ganti NSData dengan Swift 3+

Operasi gambar umum (seperti png & jpg keduanya):

if let img = UIImage(named: "TestImage.png") {  //UIImage(named: "TestImage.jpg")
        if let data:Data = UIImagePNGRepresentation(img) {
               handleOperationWithData(data: data)     
        } else if let data:Data = UIImageJPEGRepresentation(img, 1.0) {
               handleOperationWithData(data: data)     
        }
}

*******
func handleOperationWithData(data: Data) {
     // Handle operations with data here...
     if let image = UIImage(data: data) {
        // Use image...
     }
}

Dengan menggunakan ekstensi:

extension UIImage {

    var pngRepresentationData: Data? {
        return UIImagePNGRepresentation(self)
    }

    var jpegRepresentationData: Data? {
        return UIImageJPEGRepresentation(self, 1.0)
    }
}

*******
if let img = UIImage(named: "TestImage.png") {  //UIImage(named: "TestImage.jpg")
      if let data = img.pngRepresentationData {
              handleOperationWithData(data: data)     
      } else if let data = img.jpegRepresentationData {
              handleOperationWithData(data: data)     
     }
}

*******
func handleOperationWithData(data: Data) {
     // Handle operations with data here...
     if let image = UIImage(data: data) {
        // Use image...
     }
}
Krunal
sumber
4

Gambar ke Data: -

    if let img = UIImage(named: "xxx.png") {
        let pngdata = img.pngData()
    }

   if let img = UIImage(named: "xxx.jpeg") {
        let jpegdata = img.jpegData(compressionQuality: 1)
    }

Data ke Gambar: -

 let image = UIImage(data: pngData)
Yogendra Singh
sumber
1

Cepat 5

biarkan gambar yang Anda buat sebagai UIImage menjadi gambar

image.pngData() as NSData? 
dakrawat
sumber
Harap luangkan waktu sejenak untuk membaca bantuan pengeditan di pusat bantuan . Pemformatan di Stack Overflow berbeda dengan situs lain.
Dharman