Convertir UIImage en NSData et reconvertir en UIImage dans Swift?


143

J'essaie d'enregistrer un UIImageto NSData, puis de lire le NSDatados d'un nouveau UIImagedans Swift. Pour convertir le UIImageen, NSDataj'utilise le code suivant:

let imageData: NSData = UIImagePNGRepresentation(myImage)

Comment puis-je convertir imageData(c.-à-d. NSData) À nouveau UIImage?

Réponses:


155

UIImage(data:imageData,scale:1.0) en supposant que l'échelle de l'image est de 1.

Dans swift 4.2, utilisez le code ci-dessous pour obtenir des données ().

image.pngData()

67

Merci. M'a beaucoup aidé. Converti en Swift 3 et travaillé

Sauver: let data = UIImagePNGRepresentation(image)

Charger: let image = UIImage(data: data)


1
N'est-ce pas let imagePt = UIImage(data: caminhodaImagem)assez?
superarts.org


17

Maintenant, dans Swift 4.2, vous pouvez utiliser la pngData()nouvelle méthode d'instance de UIImagepour obtenir les données de l'image

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

Swift 4.2 est-il en version bêta? Je ne vois pas cette fonction disponible
Daniel Springer

on dirait qu'il a été renommé
吖 奇 说 - 何魏奇 Archy Will He

'pngData ()' a été renommé en 'UIImagePNGRepresentation (_ :)'
j2abro

9

Détails

  • Xcode 10.2.1 (10E1001), Swift 5

Solution 1

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

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

Utilisation de la solution 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")

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

Utilisation de la solution 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)

Problèmes

La représentation d'image prendra beaucoup de ressources CPU et mémoire. Donc, dans ce cas, il vaut mieux suivre plusieurs règles:

- ne pas exécuter jpegData (compressionQuality :) sur la file d'attente principale

- exécuter un seul jpegData (compressionQuality :) simultanément

Faux:

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

Droite:

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

Liens


Vasily, cela a été extrêmement utile. Je suis capable de convertir UIImages en bmps en utilisant votre code. J'ai également besoin de supprimer alpha de bmp. J'ai essayé de définir des options pour supprimer l'alpha et je n'arrive pas à l'obtenir pour se débarrasser du calque. J'appelle comme ceci: let options: NSDictionary = [kCGImagePropertyHasAlpha: false] let convertToBmp = image.toData (options: options, type: .bmp)
Gallaugher

@Gallaugher êtes-vous sûr que cela ne fonctionne pas? Essayez de créer une image png sans alpha et vérifiez-la. Il est peut-être impossible d'utiliser la propriété kCGImagePropertyHasAlpha avec bmp.
Vasily Bodnarchuk

@ vasily-bodnarchuk Merci pour le lead (et le code précédent). Je me suis débarrassé de l'alpha - je ne pouvais pas le faire via png, mais j'ai utilisé resizedImage.toJpegData avec alpha comme false, puis reconverti ces données en UIImage, puis créé un toData de type .bmp. Les options n'ont pas eu d'impact, mais cette couche alpha a été supprimée dans Photoshop et a créé un fichier plus petit. Je n'arrive toujours pas à produire le format bmp graphique raster 16 bits exact dont j'ai besoin pour un PyPortal. Pour une raison quelconque, les données convoyées ne s'affichent pas lorsque je convertis via un outil comme la conversion en ligne. THX.
Gallaugher

@ vasily-bodnarchuk, le bmp que j'ai enregistré en utilisant votre code utile s'ouvre dans Photoshop avec l'option bmp "Inverser l'ordre des lignes". Si je réenregistre et décoche cette option sur l'écran "Options BMP" apparaissant après "Enregistrer sous ...", puis charge bmp sur le PyPortal, mis à jour les spectacles bmp. Je ne vois aucun document Apple qui ressemble à une option "Inverser l'ordre des lignes", je ne sais pas pourquoi cela apparaît comme sauvegarde par défaut et je ne sais pas comment "annuler" cela dans Swift. BTW: J'ai posté mes questions et fichiers connexes sur: stackoverflow.com/questions/57241391/ ... Merci!
Gallaugher

8

Pour enregistrer en tant que données:

Depuis StoryBoard, si vous souhaitez enregistrer des données "image" sur l'imageView de MainStoryBoard, les codes suivants fonctionneront.

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

Pour charger "image" dans imageView: Regardez le point d'exclamation "!", "?" de près si c'est tout à fait le même que celui-ci.

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

Le type "NSData" est automatiquement converti en type "Data" pendant ce processus.


6

Pour une exécution sûre du code, utilisez if-letblock with Datapour éviter le crash de l'application &, car la fonction UIImagePNGRepresentationrenvoie une valeur facultative.

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

Remarque: les données sont de classe Swift 3+. Utilisez des données au lieu de NSData avec Swift 3+

Opérations génériques sur les images (comme png et jpg à la fois):

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

En utilisant l'extension:

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

Image aux données: -

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

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

Données à l'image: -

 let image = UIImage(data: pngData)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.