Convertire UIImage in NSData e riconvertirlo in UIImage in Swift?


143

Sto cercando di salvare un UIImagea NSDatae quindi leggere il NSDataretro di un nuovo UIImagein Swift. Per convertire il UIImagein NSDatasto usando il seguente codice:

let imageData: NSData = UIImagePNGRepresentation(myImage)

Come posso convertire imageData(cioè, NSData) di nuovo in un nuovo UIImage?

Risposte:


155

UIImage(data:imageData,scale:1.0) presumendo che la scala dell'immagine sia 1.

In rapido 4.2, utilizzare il codice seguente per ottenere dati ().

image.pngData()

67

Grazie. Mi ha aiutato molto Convertito in Swift 3 e funzionato

Salvare: let data = UIImagePNGRepresentation(image)

Caricare: let image = UIImage(data: data)


1
Non è let imagePt = UIImage(data: caminhodaImagem)abbastanza?
superarts.org,


17

Ora in Swift 4.2 è possibile utilizzare il pngData()nuovo metodo di istanza di UIImageper ottenere i dati dall'immagine

let profileImage = UIImage(named:"profile")!
let imageData = profileImage.pngData()

Swift 4.2 è in beta? Non vedo questa funzione disponibile
Daniel Springer,

sembra che sia stato rinominato
吖 奇 说 - 何魏奇 Archy Will He il

'pngData ()' è stato rinominato in 'UIImagePNGRepresentation (_ :)'
j2abro

9

Dettagli

  • Xcode 10.2.1 (10E1001), Swift 5

Soluzione 1

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

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

Utilizzo della soluzione 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")

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

Utilizzo della soluzione 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)

I problemi

La rappresentazione delle immagini richiederà molte CPU e risorse di memoria. Quindi, in questo caso è meglio seguire diverse regole:

- Non eseguire jpegData (compressioneQuality :) sulla coda principale

- esegue solo un jpegData (compressioneQualità :) contemporaneamente

Sbagliato:

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

Destra:

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

link


Vasily, questo è stato di grande aiuto. Sono in grado di convertire UIImages in bmps usando il tuo codice. Devo anche rimuovere l'alfa da bmp. Ho provato a impostare le opzioni per rimuovere l'alfa e non riesco a farlo per sbarazzarmi del livello. Sto chiamando in questo modo: let options: NSDictionary = [kCGImagePropertyHasAlpha: false] let convertToBmp = image.toData (opzioni: opzioni, tipo: .bmp)
Gallaugher

@Gallaugher sei sicuro che non funzioni? Prova a creare un'immagine png senza alfa e controllala. Potrebbe essere impossibile usare la proprietà kCGImagePropertyHasAlpha con bmp.
Vasily Bodnarchuk,

@ vasily-bodnarchuk Grazie per il lead (e il codice precedente). Mi sono sbarazzato dell'alfa - non sono riuscito a farlo tramite png, ma ho usato resizedImage.toJpegData con alpha come falso, quindi ho riconvertito questi dati in un UIImage, quindi ho fatto un toData di tipo .bmp. Le opzioni non hanno avuto alcun impatto, ma questo ha rimosso il livello alfa in Photoshop e ha creato un file più piccolo. Non riesco ancora a produrre l'esatto formato bmp grafico raster a 16 bit di cui ho bisogno per un PyPortal. Per qualche motivo i dati convinti non vengono visualizzati per do quando converto tramite uno strumento come il convertitore online. Grazie.
Gallaugher,

@ vasily-bodnarchuk, il bmp che ho salvato usando il tuo utile codice si apre in Photoshop con l'opzione blip "Capovolgi ordine". Se riesco a salvare e deselezionare questa opzione nella schermata "Opzioni BMP" che appare dopo "Salva come ...", quindi carico bmp su PyPortal, viene visualizzato bmp aggiornato. Non vedo alcun documento Apple che assomigli a un'opzione "Capovolgi ordine", non sono sicuro del motivo per cui questo viene visualizzato come salvataggio predefinito e non sono sicuro di come "annullarlo" in Swift. A proposito: ho pubblicato la mia Q e i file correlati su: stackoverflow.com/questions/57241391/… Grazie!
Gallaugher,

8

Per salvare come dati:

Da StoryBoard, se si desidera salvare i dati "image" su imageView di MainStoryBoard, i seguenti codici funzioneranno.

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

Per caricare "image" in imageView: guarda il punto esclamativo "!", "?" da vicino se è abbastanza uguale a questo.

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

Il tipo "NSData" viene convertito automaticamente nel tipo "Dati" durante questo processo.


6

Per un'esecuzione sicura del codice, utilizzare il if-letblocco con Dataper impedire l'arresto anomalo dell'app e, poiché la funzione UIImagePNGRepresentationrestituisce un valore opzionale.

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

Nota: i dati sono di classe Swift 3+. Usa i dati anziché NSData con Swift 3+

Operazioni generiche con le immagini (come png e jpg):

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

Utilizzando l'estensione:

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

4

Immagine a dati: -

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

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

Dati all'immagine: -

 let image = UIImage(data: pngData)

1

Swift 5

lascia che l'immagine che crei come UIImage sia immagine

image.pngData() as NSData? 

Ti preghiamo di dedicare un momento alla lettura della guida alla modifica nel Centro assistenza . La formattazione su Stack Overflow è diversa rispetto ad altri siti.
Dharman,
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.