Konwertować UIImage na NSData i konwertować z powrotem do UIImage w Swift?


142

Próbuję zapisać UIImagedo, NSDataa następnie przeczytać NSDatapowrót do nowego UIImagew Swift. Aby przekonwertować UIImagedo NSDataUżywam następujący kod:

let imageData: NSData = UIImagePNGRepresentation(myImage)

Jak przekonwertować imageData(tj. NSData) Z powrotem na nowy UIImage?

Odpowiedzi:


155

UIImage(data:imageData,scale:1.0) przy założeniu, że skala obrazu wynosi 1.

W Swift 4.2 użyj poniższego kodu do get Data ().

image.pngData()

66

Dzięki. Bardzo mi pomogło. Przekonwertowany na Swift 3 i działał

Zapisać: let data = UIImagePNGRepresentation(image)

Załadować: let image = UIImage(data: data)


1
Nie let imagePt = UIImage(data: caminhodaImagem)wystarczy?
superarts.org,


17

Teraz w Swift 4.2 możesz użyć pngData()nowej metody instancji, UIImageaby pobrać dane z obrazu

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

Czy Swift 4.2 jest w wersji beta? Nie widzę tej funkcji dostępnej
Daniel Springer

wygląda na to, że została zmieniona
吖 奇 说 - 何魏奇 Archy Will He

Nazwa „pngData ()” została zmieniona na „UIImagePNGRepresentation (_ :)”
j2abro

9

Detale

  • Xcode 10.2.1 (10E1001), Swift 5

Rozwiązanie 1

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

Rozwiązanie 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
        }
    }
}

Zastosowanie rozwiązania 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")

Rozwiązanie 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
            }
        }
    }
}

Zastosowanie rozwiązania 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)

Problemy

Obraz reprezentujący zajmie dużo zasobów procesora i pamięci. Tak więc w tym przypadku lepiej przestrzegać kilku zasad:

- nie uruchamiaj jpegData (CompressionQuality :) na głównej kolejce

- uruchamiaj jednocześnie tylko jeden plik jpegData (compressQuality :)

Źle:

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

Dobrze:

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

Spinki do mankietów


Wasilij, to było niezwykle pomocne. Jestem w stanie przekonwertować UIImages na bmps za pomocą twojego kodu. Muszę też usunąć alfa z bmp. Próbowałem ustawić opcje, aby usunąć alfa i nie wydaje się, aby pozbyć się warstwy. Wołam w ten sposób: let options: NSDictionary = [kCGImagePropertyHasAlpha: false] let convertToBmp = image.toData (opcje: opcje, typ: .bmp)
Gallaugher

@Gallaugher czy jesteś pewien, że to nie działa? Spróbuj stworzyć obraz png bez alfa i sprawdź to. Być może niemożliwe jest użycie właściwości kCGImagePropertyHasAlpha z bmp.
Wasilij Bodnarchuk

@ vasily-bodnarchuk Dzięki za prowadzenie (i wcześniejszy kod). Pozbyłem się alfy - nie mogłem tego zrobić przez png, ale użyłem resizedImage.toJpegData z alpha jako false, a następnie przekonwertowałem te dane z powrotem na UIImage, a następnie wykonałem toData typu .bmp. Opcje nie miały wpływu, ale spowodowało to usunięcie warstwy alfa w Photoshopie i utworzenie mniejszego pliku. Nadal nie mogę utworzyć dokładnego 16-bitowego formatu bmp grafiki rastrowej, którego potrzebuję dla PyPortal. Z jakiegoś powodu dane konwertowane nie są wyświetlane przez do, gdy konwertuję za pomocą narzędzia takiego jak konwersja online. Dzięki.
Gallaugher

@ vasily-bodnarchuk, plik bmp, który zapisałem przy użyciu pomocnego kodu, otwiera się w programie Photoshop z opcją bmp „Odwróć kolejność wierszy”. Jeśli ponownie zapiszę i odznaczę tę opcję na ekranie „Opcje BMP” pojawiającym się po „Zapisz jako ...”, załaduj bmp na PyPortal, zaktualizowane programy bmp. Nie widzę żadnych dokumentów Apple, które wyglądają jak opcja „Odwróć kolejność wierszy”. Nie jestem pewien, dlaczego jest to domyślne zapisywanie i nie wiem, jak to „cofnąć” w języku Swift. BTW: Moje pytania i pliki powiązane zostały opublikowane pod adresem: stackoverflow.com/questions/57241391/… Dzięki!
Gallaugher

8

Aby zapisać jako dane:

W StoryBoard, jeśli chcesz zapisać dane „obrazu” w imageView w MainStoryBoard, będą działać następujące kody.

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

Aby załadować „obraz” do imageView: spójrz na wykrzyknik „!”, „?” dokładnie, czy to jest to samo, co ten.

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

Typ „NSData” jest automatycznie konwertowany na typ „Data” podczas tego procesu.


6

W celu bezpiecznego wykonania kodu użyj if-letbloku z, Dataaby zapobiec awariom aplikacji, ponieważ funkcja UIImagePNGRepresentationzwraca wartość opcjonalną.

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

Uwaga: dane są klasy Swift 3+. Użyj danych zamiast NSData w Swift 3+

Ogólne operacje na obrazach (zarówno png, jak i 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...
     }
}

Korzystając z rozszerzenia:

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

Obraz do danych: -

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

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

Dane do obrazu: -

 let image = UIImage(data: pngData)

1

Szybki 5

niech obraz, który tworzysz jako UIImage, będzie obrazem

image.pngData() as NSData? 

Poświęć chwilę na przeczytanie pomocy dotyczącej edycji w Centrum pomocy . Formatowanie w witrynie Stack Overflow jest inne niż w innych witrynach.
Dharman,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.