Chuyển đổi UIImage sang NSData và chuyển đổi trở lại UIImage trong Swift?


142

Tôi đang cố gắng để tiết kiệm UIImageđến NSDatavà sau đó đọc NSDatalại một mới UIImagetrong Swift. Để chuyển đổi UIImagesang NSDatatôi đang sử dụng mã sau đây:

let imageData: NSData = UIImagePNGRepresentation(myImage)

Làm cách nào để chuyển đổi imageData(tức là NSData) trở lại mới UIImage?

Câu trả lời:


155

UIImage(data:imageData,scale:1.0) giả định tỷ lệ của hình ảnh là 1.

Trong swift 4.2, sử dụng mã bên dưới để lấy Dữ liệu ().

image.pngData()

66

Cảm ơn. Giúp tôi rất nhiều. Chuyển đổi sang Swift 3 và hoạt động

Để tiết kiệm: let data = UIImagePNGRepresentation(image)

Để tải: let image = UIImage(data: data)


1
Không let imagePt = UIImage(data: caminhodaImagem)đủ sao?
superarts.org


17

Bây giờ trong Swift 4.2, bạn có thể sử dụng pngData()phương thức cá thể mới UIImageđể lấy dữ liệu từ hình ảnh

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

Swift 4.2 có phải là bản Beta không? Tôi không thấy chức năng này khả dụng
Daniel Springer

có vẻ như nó đã được đổi tên
吖 奇 - Archy Will He

'pngData ()' đã được đổi tên thành 'UIImagePNGRepftimeation (_ :)'
j2abro

9

Chi tiết

  • Xcode 10.2.1 (10E1001), Swift 5

Giải pháp 1

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

Giải pháp 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
        }
    }
}

Sử dụng giải pháp 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")

Giải pháp 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
            }
        }
    }
}

Sử dụng giải pháp 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)

Các vấn đề

Hình ảnh đại diện sẽ mất rất nhiều tài nguyên cpu và bộ nhớ. Vì vậy, trong trường hợp này tốt hơn là tuân theo một số quy tắc:

- không chạy jpegData (compressionQuality :) trên hàng đợi chính

- chỉ chạy đồng thời một jpegData (compressionQuality :)

Sai lầm:

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

Đúng:

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

Liên kết


Vasily, điều này là rất hữu ích. Tôi có thể chuyển đổi UIImages thành bmps bằng mã của bạn. Tôi cũng cần loại bỏ alpha khỏi bmp. Tôi đã cố gắng thiết lập các tùy chọn để loại bỏ alpha và dường như không thể lấy nó ra khỏi lớp. Tôi đang gọi như thế này: hãy để các tùy chọn: NSDipedia = [kCGImagePropertyHasAlpha: false] let convertToBmp = image.toData (tùy chọn: tùy chọn, loại: .bmp)
Gallaugher 27/07/19

@Gallaugher bạn có chắc là nó không hoạt động? Cố gắng tạo hình ảnh png với alpha và kiểm tra nó. Có thể không thể sử dụng thuộc tính kCGImagePropertyHasAlpha với bmp.
Vasily Bodnarchuk

@ vasily-bodnarchuk Cảm ơn bạn đã dẫn đầu (và mã trước đó). Tôi đã loại bỏ alpha - Tôi không thể làm điều đó thông qua png, nhưng tôi đã sử dụng resizedImage.toJpegData với alpha là false, sau đó chuyển đổi dữ liệu này trở lại thành UIImage, sau đó thực hiện toData loại .bmp. Các tùy chọn không có tác động, nhưng lớp alpha đã loại bỏ này trong Photoshop và tạo một tệp nhỏ hơn. Vẫn không thể tạo định dạng bmp đồ họa raster 16 bit chính xác mà tôi cần cho PyPortal. Vì một số lý do, dữ liệu được mong muốn không hiển thị khi tôi chuyển đổi qua công cụ như chuyển đổi trực tuyến. Cám ơn.
Gallaugher

@ vasily-bodnarchuk, bmp tôi đã lưu bằng mã hữu ích của bạn sẽ mở trong Photoshop với tùy chọn bmp "Lật hàng theo thứ tự". Nếu tôi lưu lại và bỏ chọn tùy chọn này trên màn hình "Tùy chọn BMP" xuất hiện sau "Lưu dưới dạng ...", sau đó tải bmp trên PyPortal, các chương trình bmp được cập nhật. Tôi không thấy bất kỳ tài liệu nào của Apple trông giống như tùy chọn "Flip row order", tôi không chắc tại sao điều này lại xuất hiện dưới dạng lưu mặc định & tôi không chắc chắn cách "hoàn tác" điều này trong Swift. BTW: Tôi đã đăng các tập tin Q & liên quan của mình tại: stackoverflow.com/questions/57241391/ cảm ơn!
Gallaugher

8

Để lưu dưới dạng dữ liệu:

Từ StoryBoard, nếu bạn muốn lưu dữ liệu "hình ảnh" trên imageView của MainStoryBoard, các mã sau sẽ hoạt động.

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

Để tải "hình ảnh" vào imageView: Nhìn vào dấu chấm than "!", "?" chặt chẽ cho dù đó là khá giống như cái này.

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

Loại "NSData" được tự động chuyển thành loại "Dữ liệu" trong quá trình này.


6

Để thực thi mã an toàn, hãy sử dụng if-letkhối với Datađể ngăn sự cố ứng dụng &, vì hàm UIImagePNGRepresentationtrả về một giá trị tùy chọn.

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

Lưu ý: Dữ liệu là lớp Swift 3+. Sử dụng Dữ liệu thay vì NSData với Swift 3+

Các thao tác hình ảnh chung (như cả png & 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...
     }
}

Bằng cách sử dụng phần mở rộng:

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

Hình ảnh thành dữ liệu: -

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

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

Dữ liệu thành hình ảnh: -

 let image = UIImage(data: pngData)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.