如何使用 sips 或其他程序以编程方式制作具有 10 个不同图像的 Mac OS X ICNS

How to programmatically make Mac OS X ICNS with 10 different images using sips or other

我的问题是我需要。我需要以编程方式实现这一点。

因此对于 mac os x,应用程序图标应具有以下尺寸:

我有 10 张图片。每一个我都在右下角放了一个徽章,这个徽章的位置和position没有缩放。所以我有 10 张不同的图片。

如何用它制作 ICNS?

我想用 sips,但是 sips 只需要一个文件,它会做所有的缩放:http://cc.bingj.com/cache.aspx?q=mac+icns+sips+argument+list&d=5035141870911884&mkt=en-US&setlang=en-US&w=n3PZcWn6bEPxt4O96PPLd6nugtVq5jDz

有没有办法让 /usr/bin/sips 拍摄我的 10 张图片并从中制作一个 icns?如果sips不行,还有其他办法吗?

如果你想使用 iconutil,你可以这样做。至少在我的 10.9.5 系统上,它是基础 OS 的一部分。它不是像开发人员工具那样的特殊安装。您可以验证使用:

pkgutil --file-info /usr/bin/iconutil

在这里,输出:

volume: /
path: /usr/bin/iconutil

pkgid: com.apple.pkg.BSD
pkg-version: 10.9.0.1.1.1306847324
install-time: 1402788942
uid: 0
gid: 0
mode: 755

重要的部分是 pkgid。它是 BSD 软件包的一部分,是基础 OS.

的一部分

也就是说,编写一些代码来执行此操作并不难。

您可以使用 CGDestination API。使用 CGImageDestinationCreateWithURL() 创建目的地。对于 type,传递 kUTTypeAppleICNS.

鉴于您想要从单个文件添加图像,使用 CGImageSourceCreateWithURL() 为每个文件创建一个 CGImageSource 可能是最简单的方法。然后,您可以使用 CGImageDestinationAddImageFromSource() 直接将图像从源添加到目标。在将其图像添加到目标后,不要忘记 CFRelease() 每个源。

然后,调用CGImageDestinationFinalize()让目的地写出图像到URL。然后,CFRelease()目的地。

如果每个源图像都设置了正确的 DPI,则会将其原封不动地复制到目标位置。如果源图像没有正确的 DPI 设置,您可以通过将属性字典传递给 CGImageDestinationAddImageFromSource() 来覆盖它。包括键 kCGImagePropertyDPIHeightkCGImagePropertyDPIWidth,每个键都具有一个具有所需 DPI 的 CFNumber 对象的对应值。对于普通分辨率图标,使用 72 DPI。对于高分辨率 (@2x) 图标,请使用 144 DPI。


创建 ICNS 文件也可以使用旧的 IconFamily API 来完成,但它有点毛茸茸。此外,它不支持高分辨率图标。

首先,您为图标系列创建一个句柄(指向可调整大小缓冲区的指针):

IconFamilyHandle iconFamily = (IconFamilyHandle)NewHandle(0);

然后,对于每个图像大小(16、32、128、256 和 512),您为图像数据的原始位图创建一个句柄。位图应为每个像素 32 位,每个组件 8 位,ARGB 非预乘数据,无填充。

int size = /* 16, 32, 128, 256, or 512 */;
Handle handle = NewHandle(size * size * 4);
// fill handle with image data; buffer pointer is *handle

然后,您可以通过以下调用将该句柄添加到图标系列:

SetIconFamilyData(iconFamily, kIconServices16PixelDataARGB, handle);

对于其他尺寸,请将 kIconServices16PixelDataARGB 中的“16”替换为适当的值。

然后,您将图标系列句柄的数据写入文件。通过简单地取消引用句柄(即 *iconFamily)获得指向数据的指针。它的大小是通过调用 GetHandleSize((Handle)iconFamily).

获得的

通过调用 DisposeHandle().

处理您在此过程中创建的任何句柄