从UIImage获取底层NSData

111

我可以使用 [UIImage imageWithData:][UIImage initWithData:] 方法从 NSData 创建 UIImage

我想知道是否可以从现有的 UIImage 中获取 NSData,类似于 NSData *myData = [myImage getData]; 这样的操作?

7个回答

191
NSData *imageData = UIImageJPEGRepresentation(image, 0.7); // 0.7 is JPG quality
或者
NSData *imageData = UIImagePNGRepresentation(image);

根据您是想要PNG格式还是JPG格式来选择。


98
我不知道为什么这个答案会被投票赞同这么多次,也不知道为什么它被接受了。原帖问的是如何检索最初给定的数据。使用 UIImageJPEGRepresentationUIImagePNGRepresentation 会改变数据并进行重新转换。有没有真正实现所要求的方式? - Patrik
6
这个答案不好,因为如果图像已经是有损格式,那么这样做会降低图像的质量。 - 1dayitwillmake
2
@CipherCom 我明白你希望得到准确的数据。然而,我认为对于大多数遇到这个问题的人来说,这个答案会完美地满足他们的需求...这也是为什么有人给予点赞的原因。如果你找到了一个能恢复原始数据的答案,请分享一下吧 ;) - tybro0103
1
@1dayitwillmake,甚至PNG也不行吗?这不是我的专业领域,但我认为PNG不会有损失吧? - tybro0103
谢谢你让我知道!我其实不知道。有人知道如何用C#做吗? - Penjimon
显示剩余3条评论

28

当使用init(data: originalData)初始化UIImage对象时,originalData会被转换为某种内部格式的原始数据。稍后可以使用以下方法检索这些数据:

let rawData = myImage.cgImage?.dataProvider?.data as Data?

然而,由于rawData是原始数据,因此它的大小甚至比使用UIImagePNGRepresentation时还要大。


我该如何在Objective-C中实现这个? - h3dkandi
1
NSData *rawData = (__bridge NSData *) CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));NSData *rawData = (__bridge NSData *) CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage)); - ZardozSpeaks
@ZardozSpeaks,Obj-C的变体完全可以作为这个答案的编辑包含进去。 - Kamil.S

12

Swift 4.2

let dataPng = image.pngData() // return image as PNG. May return nil if image has no CGImageRef or invalid bitmap format

let dataJpg = image.jpegData(compressionQuality: 1) // return image as JPEG. May return nil if image has no CGImageRef or invalid bitmap format. compression is 0(most)..1(least)

8

我偶然发现这篇文章,而且我喜欢Swift :)

以下是Caroline文章的Swift版本。

var imageData = UIImagePNGRepresentation(image)

或者

var imageData = UIImageJPEGRepresentation(image, 0.7) 

问题不是关于Swift的。 - Cross_
我要点赞nsij的回答,Cross,因为它真的很有帮助!!! - stromyc

6

你可以将UIImage视为一个用于显示格式的对象,因此它不会使用原始数据(可能是PNG或JPEG格式),而更有可能是像素数组或其他内部格式。换句话说,UIImage(data: foo) 不会保留 foo

  1. If you just want to use it elsewhere in your program, the original UIImage will do fine (I presume that's not actually the case here)

  2. If you want to serialise, UIImagePNGRepresentation(...) will work but will be oversized if the original was a JPEG; UIImageJPEGRepresentation(...) will often result in slightly oversize data and is slightly lossy if your original was PNG. It should be okay to pick one based on the way the image will be displayed and the format you expect to be provided. If you happen to be using PNG in and want PNG out, you should get a good file size and almost identical data, special PNG chunks aside.

  3. If you want to get an exact copy of the original data (perhaps to save a file after thumbnailing, or to SHA1 it), then you need to retain it separately. You might do something like:

    var image:UIImage
    var imageData:NSData {
        didSet {
            image = UIImage(data: imageData)
        }
    }
    

0

我发现序列化/反序列化UIImage(通过Data)的唯一解决方案是使用this solution

然后,您可以使用UIImage上的扩展方法进行序列化/反序列化,而不管UIImage是如何创建的:

let originalImage: UIImage = ...
let cgData = image.cgImage!.png!
let image = UIImage(data: cgData)!

-2

自从上面的答案发布以来,情况已经发生了变化,对于那些仍在寻找解决方案的人,因为他们和CipherCom一样担心:iOS 5已经添加了CIImage property


我没有看到使用CIImage获取底层NSData的方法...我有什么遗漏吗? - tybro0103
4
这不会有所帮助。如果使用的是“imageWithCIImage:”初始化,属性“CIImage”才会被设置。而且这不是直接使用的数据,而是另一个图像表示对象。 - Patrik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接