Converter UIImage em NSData e converter novamente em UIImage no Swift?

142

Estou tentando salvar um UIImagepara NSDatae depois ler as NSDatacostas para um novo UIImageno Swift. Para converter UIImagepara NSData, estou usando o seguinte código:

let imageData: NSData = UIImagePNGRepresentation(myImage)

Como faço para converter imageData(ou seja NSData) de volta para um novo UIImage?

pete
fonte

Respostas:

155

UIImage(data:imageData,scale:1.0) presumindo que a escala da imagem é 1.

No swift 4.2, use o código abaixo para obter Data ().

image.pngData()
algal
fonte
66

Obrigado. Me ajudou muito. Convertido para Swift 3 e trabalhou

Salvar: let data = UIImagePNGRepresentation(image)

Para carregar: let image = UIImage(data: data)

Ivan Sinigaglia
fonte
1
Não é let imagePt = UIImage(data: caminhodaImagem)suficiente?
superarts.org 15/09/17
32

Use o imageWithData:método, que é traduzido para o Swift comoUIImage(data:)

let image : UIImage = UIImage(data: imageData)
dasblinkenlight
fonte
17

Agora, no Swift 4.2, você pode usar o pngData()novo método de instância UIImagepara obter os dados da imagem

let profileImage = UIImage(named:"profile")!
let imageData = profileImage.pngData()
Sh_Khan
fonte
O Swift 4.2 está na versão beta? Não vejo essa função disponível
Daniel Springer
parece que ele foi renomeado
吖 奇 说 - 何魏奇 Archy Will He
'pngData ()' foi renomeado para 'UIImagePNGRepresentation (_ :)'
j2abro 14/03/19
9

Detalhes

  • Xcode 10.2.1 (10E1001), Swift 5

Solução 1

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

Solução 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
        }
    }
}

Uso da solução 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")

Solução 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
            }
        }
    }
}

Uso da solução 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)

Problemas

A representação da imagem consumirá muitos recursos de CPU e memória. Portanto, neste caso, é melhor seguir várias regras:

- não execute jpegData (pressionQuality :) na fila principal

- execute apenas um jpegData (pressionQuality :) simultaneamente

Errado:

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

Certo:

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

Ligações

Vasily Bodnarchuk
fonte
Vasily, isso foi extremamente útil. Sou capaz de converter UIImages em bmps usando seu código. Também preciso remover o alfa do bmp. Eu tentei definir opções para remover o alfa e não consigo obtê-lo para se livrar da camada. Eu estou chamando assim: vamos opções: NSDictionary = [kCGImagePropertyHasAlpha: false] deixar convertToBmp = image.toData (opções: opções, tipo: .bmp)
Gallaugher
@ Gallaugher você tem certeza de que não está funcionando? Tente criar uma imagem png sem alfa e verifique-a. Pode ser impossível usar a propriedade kCGImagePropertyHasAlpha com bmp.
Vasily Bodnarchuk
@ vasily-bodnarchuk Obrigado pela liderança (e pelo código anterior). Eu me livrei do alpha - não podia fazê-lo através do png, mas usei resizedImage.toJpegData com alpha como false, depois converti esses dados novamente em UIImage e, em seguida, fiz um toData do tipo .bmp. As opções não tiveram impacto, mas isso removeu a camada alfa no Photoshop e criou um arquivo menor. Ainda não é possível produzir o formato bmp gráfico raster de 16 bits exato necessário para um PyPortal. Por alguma razão, os dados convocados não são exibidos quando o faço através de uma ferramenta como a conversão online. THX.
28419 Gallaugher
@ vasily-bodnarchuk, o bmp que eu salvei usando seu código útil é aberto no Photoshop com a opção bmp "Flip row order". Se eu salvar de novo e desmarcar esta opção na tela "Opções de BMP" exibida após "Salvar como ...", carregue bmp no PyPortal, mostra o bmp atualizado. Não vejo nenhum documento da Apple que se pareça com uma opção "Ordem de linha inversa". Não sei por que isso aparece como o salvamento padrão e não sei como "desfazer" isso no Swift. BTW: Publiquei meus arquivos de perguntas e respostas em: stackoverflow.com/questions/57241391/… Obrigado!
Gallaugher
8

Para salvar como dados:

No StoryBoard, se você deseja salvar os dados da "imagem" no imageView do MainStoryBoard, os seguintes códigos funcionarão.

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

Para carregar "imagem" no imageView: Observe o ponto de exclamação "!", "?" de perto se é exatamente igual a este.

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

O tipo "NSData" é convertido no tipo "Dados" automaticamente durante esse processo.

zemunkh
fonte
6

Para uma execução segura do código, use o if-letbloco com Datapara impedir a falha do aplicativo &, pois a função UIImagePNGRepresentationretorna um valor opcional.

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

Nota: Os dados são da classe Swift 3+. Use Dados em vez de NSData com Swift 3+

Operações genéricas de imagem (como 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...
     }
}

Usando a extensão:

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
fonte
4

Imagem para Dados: -

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

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

Dados para a imagem: -

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

Swift 5

deixe a imagem que você criar como UIImage seja imagem

image.pngData() as NSData? 
dakrawat
fonte
Por favor, tome um momento para ler a ajuda de editar no centro de ajuda . A formatação no estouro de pilha é diferente de outros sites.
Dharman