将UIImage转换为NSData并在Swift中转换回UIImage?


142

我正在尝试保存UIImageNSData,然后在Swift中读NSData回新UIImage的内容。要转换UIImageNSData我使用下面的代码:

let imageData: NSData = UIImagePNGRepresentation(myImage)

如何将imageData(即NSData)转换回新的UIImage

Answers:


155

UIImage(data:imageData,scale:1.0) 假设图像的比例为1。

在Swift 4.2中,将以下代码用于get Data()。

image.pngData()



17

现在,在Swift 4.2中,您可以使用的pngData()新实例方法UIImage从图像获取数据

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

是Swift 4.2 Beta版吗?我看不到此功能可用
Daniel Springer

看起来像它已经重命名了
吖奇说-何魏奇Archy Will He

'pngData()'已重命名为'UIImagePNGRepresentation(_ :)'
j2abro

9

细节

  • Xcode 10.2.1(10E1001),Swift 5

解决方案1

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

解决方案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
        }
    }
}

解决方案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")

解决方案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
            }
        }
    }
}

解决方案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)

问题

图像表示将占用大量cpu和内存资源。因此,在这种情况下,最好遵循以下规则:

-不要在主队列上运行jpegData(compressionQuality :)

-同时仅运行一个jpegData(compressionQuality :)

错误:

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

对:

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

链接


瓦西里,这很有帮助。我可以使用您的代码将UIImages转换为bmps。我还需要从bmp中删除alpha。我尝试设置选项以删除Alpha,但似乎无法摆脱它。我这样叫:let options:NSDictionary = [kCGImagePropertyHasAlpha:false] let convertToBmp = image.toData(options,options,type:.bmp)
Gallaugher

@Gallaugher您确定它不起作用吗?尝试创建不含Alpha的png图像并进行检查。可能无法在bmp中使用kCGImagePropertyHasAlpha属性。
瓦西里·博德纳丘克

@ vasily-bodnarchuk感谢您的领导(以及之前的代码)。我摆脱了alpha-我无法通过png做到这一点,但是我使用resizeImage.toJpegData并将alpha设置为false,然后将数据转换回UIImage,然后执行了.bmp类型的toData。选项没有影响,但是这删除了Photoshop中的Alpha层并创建了一个较小的文件。仍然无法产生PyPortal所需的确切16位栅格图形bmp格式。由于某些原因,当我通过在线转换之类的工具进行转换时,无法显示令人垂涎的数据。谢谢。
加洛

@ vasily-bodnarchuk,使用您的有用代码保存的bmp在Photoshop中打开,带有bmp选项“翻转行顺序”。如果我在“另存为...”之后出现的“ BMP选项”屏幕上重新保存并取消选中此选项,则将bmp加载到PyPortal上,显示更新的bmp。我没有看到任何看起来像“翻转行顺序”选项的Apple文档,我不确定为什么这会显示为默认保存,也不确定如何在Swift中“撤消”此操作。顺便说一句:我已经将我的问题和相关文件发布在:stackoverflow.com/questions/57241391/…谢谢!
加洛

8

要保存为数据:

从StoryBoard,如果要将“图像”数据保存在MainStoryBoard的imageView上,则可以使用以下代码。

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

要将“图像”加载到imageView:请查看感叹号“!”,“?” 密切相关,是否与此相同。

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

在此过程中,“ NSData”类型将自动转换为“ Data”类型。


6

为了安全执行代码,请使用if-letwith Data阻止以防止应用崩溃&,因为函数会UIImagePNGRepresentation返回一个可选值。

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

注意:数据为Swift 3+类。在Swift 3+中使用数据代替NSData

通用图像操作(如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...
     }
}

通过使用扩展名:

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

图片到数据:

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

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

数据到图像:-

 let image = UIImage(data: pngData)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.