如何将NSImage保存为新文件


75

如何在特定目录中将NSImage保存为新文件(png,jpg,...)?


4
我添加了一笔赏金,因为有人称第一个选项为丑陋的骇客,我似乎无法轻易在Google上找到一个看似正确和确定的答案,请更多投票/答案。
罗曼·泰切

Answers:


49

做这样的事情:


6
您应该以比假定它是第一个表示形式更可靠的方式获得位图图像表示。您也不能假设有一个。例如,如果图像是从PDF加载的,则将有一个NSPDFImageRep,而不是NSBitmapImageRep。
Peter Hosey 2010年

14
这是越野车。请参阅下面的常规答案。
尼尔2010年

6
如果有人找到[* representationUsingType:properties:]: unrecognized selector sent to instance解决方法,请点击这里:NSCGImageSnapshotRep,如何获取bitmapData
Joshcodes 2013年

162

您可以像这样向NSImage添加类别

调用“ TIFFRepresentation”是必不可少的,否则您可能无法获得有效的图像。


3
但是TIFF是RGB,会丢弃任何透明度信息。
2013年

4
不,TIFF可以处理Alpha和多页图像。是什么让您想到了?这就是Apple建议将其作为视网膜图像(多表示TIFF)的目标格式。
uliwitness 2014年


它会支持Gif吗?
ColdSteel

什么是ImageProps?这个值传递了什么?
ColdSteel

34

不确定其余的人,但我更喜欢吃我的全麦卷饼。上面描述的内容将起作用,并且没有任何问题,但是我发现有一些遗漏之处。在这里,我将重点介绍我的观察:

  • 首先,提供最好的表示,即使图像分辨率大于该值,它也似乎是72 DPI。所以你失去了决心
  • 其次,如何处理多页图像,例如动画GIF或PDF中的图像。继续,尝试动画GIF,您会发现动画丢失了
  • 最后,所有元数据(例如EXIF,GPS等)数据都将丢失。

因此,如果您要转换该图像,您是否真的想输掉所有这些?如果您想吃饱的饭,那么请继续阅读...

有时候,而且我确实表示有时候,没有什么比旧学校的良好发展更好。是的,这意味着我们需要做一些工作!

让我们开始吧:

我在NSData中创建一个类别。这些是类方法,因为您希望这些东西是线程安全的,没有什么比将您的东西放到栈上更安全的了。有两种类型的方法,一种用于输出非多页图像,另一种用于输出多页图像。

单个图像列表: JPG,PNG,BMP,JPEG-2000

多个图像列表: PDF,GIF,TIFF

首先在内存中创建一个可变的数据空间。

其次获得CGImageSourceRef。是的,听起来已经很丑了。并没有那么糟,让我们继续吧...您确实希望源映像不是数据的表示形式或NSImage块。但是,我们确实有一个小问题。源可能不兼容,因此请确保您根据CGImageSourceCopyTypeIdentifiers()中列出的内容检查UTI

一些代码:

等待一秒钟,为什么NSImage在那里?好吧,有些格式没有元数据,并且CGImageSource不支持,但是这些是有效的图像。一个例子是旧式的PICT图像。

现在我们有了一个CGImageSourceRef,确保它不是nil,然后让我们获取一个CGImageDestinationRef。哇,所有这些裁判都在跟踪。到目前为止,我们是2点!

我们将使用此函数:CGImageDestinationCreateWithData()

  • 第一个参数是您的imageData(广播CFMutableDataRef)
  • 第二参数是您的输出UTI,请记住上面的列表。(例如kUTTypePNG)
  • 第三参数是要保存的图像数。对于单个图像文件,该值为1,否则您可以简单地使用以下命令:

    CGImageSourceGetCount(imageSource);

  • 第四参数为零。

检查是否有CGImageDestinationRef,现在让我们将源中的图像添加到其中...这还将包括任何/所有元数据并保留分辨率。

对于多个图像,我们循环:

对于单个图像,它是在索引0处的一行代码:

好的,完成将其写入磁盘或数据容器的操作:

这样一来,可变数据从一开始就拥有我们所有的图像数据和元数据。

我们完成了吗?几乎,即使有垃圾收集,您也必须清理!请记住,两个Ref代表来源,一个代表目的地,所以CFRelease()

现在我们完成了,最终得到的是保留所有元数据,分辨率等的转换图像。

我的NSData类别方法如下所示:

调整大小或ICO / ICNS怎么样?这是另一天,但总而言之,您首先要解决调整大小的问题...

  1. 创建具有新大小的上下文:CGBitmapContextCreate()
  2. 从索引获取图像引用:CGImageSourceCreateImageAtIndex()
  3. 获取元数据的副本:CGImageSourceCopyPropertiesAtIndex()
  4. 将图像绘制到上下文中:CGContextDrawImage()
  5. 从上下文获取调整大小的图像:CGBitmapContextCreateImage()
  6. 现在将图像和元数据添加到目标引用:CGImageDestinationAddImage()

冲洗并重复执行源中嵌入的多个图像。

ICO和ICNS的唯一区别是,一个文件是一个图像,而另一个文件是一个文件中的多个图像。打赌,你可以猜哪个是哪个?;-)对于这些格式,您必须将尺寸调整为特定的尺寸,否则将导致ERROR。尽管使用适当的UTI的过程完全相同,但是调整大小要严格一些。

好的,希望这对其他人有帮助,您和我一样充实!

对不起,忘了提。当您获得NSData对象时,可以根据需要使用它,例如writeToFile,writeToURL或根据需要创建另一个NSImage。

祝您编码愉快!


2
这是一个很好的开始,当然比其他答案要好(即使这些答案的评分更高),但还不完整。首先,这里介绍的逻辑本身无法处理PDF文件(CGImageDestinationAddImageFromSource将不起作用,因为图像源将为nil)。PDF和其他不可复制的图像源需要特殊处理(通过缩略图获取图像或以其他方式复制数据)。其次,它本身不会复制任何元数据,您需要通过从图像源检索属性字典并将其添加到图像目的地来显式地进行复制。
danielv

请问两个问题。1)如何确定[anImage TIFFRepresentation]始终返回某些内容?没有没有TIFFRepresentation的NSImage吗?2)您能否为这些功能中的至少一个(例如JPEPDataFromURL)提供完整的工作顺序代码片段?我试图按照您的指示进行操作,至少对我来说是行不通的(我试图将传入的视频数据帧以JPEG格式保存到磁盘,并且我的输入来自AVSession的CMSampleBuffer并通过NSImage-我尝试使用您的代码将其保存到文件中
Motti Shneor 19''Apr

15

Swift 4.2解决方案


您能解释为什么用self.self代替self吗?有什么区别吗?
MartinW

原来没有区别。也许这是swift的早期版本,但我认为它使用了显式的类名打印,但看起来好像只是返回<<Class-Name> <Memory-Address>>
Charlton Provatas

14

使用swift3另存为PNG


让tiffData = image.tiffRepresentation!let imageRep = NSBitmapImageRep(data:tiffData)let data = imageRep?.representation(using:.PNG,properties:[:])do {try data?.write(to:URL(fileURLWithPath:path3),options:NSData.WritingOptions ())} catch {print(“((error)”))}
希望

5

迅捷风格:


2

为了帮助跨平台代码,我实现了一个UIImagePNGRepresentation()在Mac上运行的版本(并使用NSImage)。

用法:


1

使用SWIFT可以保证的另一种可行方法:

我有一个“图像井”,用户可以在其中放置任何图像。并且此“ Image Well”具有可通过出口访问的image属性(类型为NSImage):

保存该图像的代码(您可以将其放入按钮动作中)是:

在给定代码的第一行中,我们检查Image Well是否有图像。

在第二行中,我们对该图像进行位图表示。

在第三行中,我们将BitmapRepresentation转换为JPG类型,其压缩系数设置为“ 1”(无压缩)。

在第四行中,我们以给定路径保存JPG数据。“ atomically:true”表示将文件保存为一个文件,这可以确保操作成功。

注意:您可以在第三行中使用另一个NSBitmapImageFileType,以将图像保存为另一种格式。它有很多:

等等


0

带和不带压缩的Objc解决方案

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.