以编程方式创建ICNS: [英] Creating an ICNS programmatically: "Unsupported Image Size"

查看:78
本文介绍了以编程方式创建ICNS:的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试以编程方式创建ICNS(包括1024x1024图像).当前,我正在创建一个NSImage,然后创建具有适当分辨率的CGImageRef对象,最后我使用CGImageDestinationAddImage()将它们添加到图标中. Peter Hosey已经帮助我创建了"@ 2x"图像,但是这些图像的大小无法设置.

I'm trying to create an ICNS (including a 1024x1024 image) programmatically. Currently I'm creating an NSImage, then I create CGImageRef objects with the appropriate resolution, finally I'm adding them to an icon by using CGImageDestinationAddImage(). Peter Hosey has helped me create '@2x' images already, but the sizes of the images don't wanna be set.

这是代码(仍然有些混乱,sourcefile代表图像的路径):

This is the code (still a bit messy, sourcefile represents the path to the image):

NSSize sizes[10];
sizes[0] = NSMakeSize(1024,1024);
sizes[1] = NSMakeSize(512,512);
sizes[2] = NSMakeSize(512,512);
sizes[3] = NSMakeSize(256,256);
sizes[4] = NSMakeSize(256,256);
sizes[5] = NSMakeSize(128,128);
sizes[6] = NSMakeSize(64,64);
sizes[7] = NSMakeSize(32,32);
sizes[8] = NSMakeSize(32,32);
sizes[9] = NSMakeSize(16,16);
int count = 0;
for (int i=0 ; i<10 ; i++) {
    if ([[NSUserDefaults standardUserDefaults] boolForKey:[NSString stringWithFormat:@"Size%i",i+1]]) count++;
}
NSURL *fileURL = [NSURL fileURLWithPath:aPath];

// Create icns
CGImageDestinationRef dr = CGImageDestinationCreateWithURL((CFURLRef)fileURL, kUTTypeAppleICNS , count, NULL);
NSImage *img = [[NSImage alloc] initWithContentsOfFile:sourcefile];
for (int i=0 ; i<10 ; i++) {
    if ([[NSUserDefaults standardUserDefaults] boolForKey:[NSString stringWithFormat:@"Size%i",i+1]]) {

        // Create dictionary
        BOOL is2X = true;
        if (i == 1 || i == 3 || i == 5 || i == 7 || i == 9) is2X = false;
        int dpi = 144, size = (int)(sizes[i].width/2);
        if (!is2X) {dpi = 72;size = sizes[i].width;}
        [img setSize:NSMakeSize(size,size)];
        for (NSImageRep *rep in [img representations])[rep setSize:NSMakeSize(size,size)];
        const void *keys[2] = {kCGImagePropertyDPIWidth, kCGImagePropertyDPIHeight};
        const void *values[2] = {CFNumberCreate(0, kCFNumberSInt32Type, &dpi), CFNumberCreate(0, kCFNumberSInt32Type, &dpi)};
        CFDictionaryRef imgprops = CFDictionaryCreate(NULL, keys, values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

        // Add image
        NSRect prect = NSMakeRect(0,0,size,size);
        CGImageRef i1 = [img CGImageForProposedRect:&prect context:nil hints:nil];
        CGImageDestinationAddImage(dr, i1, imgprops);
    }
}
CGImageDestinationFinalize(dr);
CFRelease(dr);

size是当前图像应为的宽度或高度.如果我们要制作"@ 2x"图像,则dpi为144,否则为72.这些值已通过NSLog进行了检查.

size is the width or height that the current image should be. dpi is 144 if we're making an '@2x' image, otherwise it's 72. These values have been checked with NSLog.

生成的ICNS文件中的图像大小均与输入图像相同.如果输入图像的大小为1024x1024,则ImageIO会抱怨:

The images in the resulting ICNS file are all the same size as the input image. If the size of the input image is 1024x1024, ImageIO complains:

ImageIO:_CGImagePluginWriteICNS不支持的图像尺寸(1024 x 1024)-缩放比例:1

ImageIO: _CGImagePluginWriteICNS unsupported image size (1024 x 1024) - scaling factor: 1

每次dpi为72,大小为1024x1024时,都会显示上述错误.

The above error is displayed every time the dpi is 72 and the size is 1024x1024.

我需要知道如何设置要添加到ICNS文件中的CGImage的大小.

我记录了图像:

2012-12-31 12:48:51.281 Eicon [912:680f] | NSImage 0x101b4caf0 大小= {512,512}重复次数=(

2012-12-31 12:48:51.281 Eicon[912:680f] |NSImage 0x101b4caf0 Size={512, 512} Reps=(

"NSBitmapImageRep 0x10380b900 Size={512, 512} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=1024x1024 Alpha=YES

Planar = NO Format =(尚未加载)CurrentBacking = nil(故障) CGImageSource = 0x10380ae70"

Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x10380ae70"

)|

2012-12-31 12:48:52.058 Eicon [912:680f] | NSImage 0x101b4caf0 大小= {512,512}代表=(

2012-12-31 12:48:52.058 Eicon[912:680f] |NSImage 0x101b4caf0 Size={512, 512} Reps=(

"NSBitmapImageRep 0x10380b900 Size={512, 512} ColorSpace=Generic RGB colorspace BPS=8 BPP=32 Pixels=1024x1024 Alpha=YES Planar=NO

Format = 2 CurrentBacking = | CGImageRef:0x101c14630 | CGImageSource = 0x10380ae70"

Format=2 CurrentBacking=|CGImageRef: 0x101c14630| CGImageSource=0x10380ae70"

)|

2012-12-31 12:48:52.111 Eicon [912:680f] | NSImage 0x101b4caf0 大小= {256,256}重复次数=(

2012-12-31 12:48:52.111 Eicon[912:680f] |NSImage 0x101b4caf0 Size={256, 256} Reps=(

"NSBitmapImageRep 0x10380b900 Size={256, 256} ColorSpace=Generic RGB colorspace BPS=8 BPP=32 Pixels=1024x1024 Alpha=YES Planar=NO

Format = 2 CurrentBacking = | CGImageRef:0x101c14630 | CGImageSource = 0x10380ae70"

Format=2 CurrentBacking=|CGImageRef: 0x101c14630| CGImageSource=0x10380ae70"

)|

2012-12-31 12:48:52.238 Eicon [912:680f] | NSImage 0x101b4caf0 大小= {256,256}重复次数=(

2012-12-31 12:48:52.238 Eicon[912:680f] |NSImage 0x101b4caf0 Size={256, 256} Reps=(

"NSBitmapImageRep 0x10380b900 Size={256, 256} ColorSpace=Generic RGB colorspace BPS=8 BPP=32 Pixels=1024x1024 Alpha=YES Planar=NO

Format = 2 CurrentBacking = | CGImageRef:0x101c14630 | CGImageSource = 0x10380ae70"

Format=2 CurrentBacking=|CGImageRef: 0x101c14630| CGImageSource=0x10380ae70"

)|

2012-12-31 12:48:52.309 Eicon [912:680f] | NSImage 0x101b4caf0 大小= {128,128}次数=(

2012-12-31 12:48:52.309 Eicon[912:680f] |NSImage 0x101b4caf0 Size={128, 128} Reps=(

"NSBitmapImageRep 0x10380b900 Size={128, 128} ColorSpace=Generic RGB colorspace BPS=8 BPP=32 Pixels=1024x1024 Alpha=YES Planar=NO

Format = 2 CurrentBacking = | CGImageRef:0x101c14630 | CGImageSource = 0x10380ae70"

Format=2 CurrentBacking=|CGImageRef: 0x101c14630| CGImageSource=0x10380ae70"

)|

2012-12-31 12:48:52.409 Eicon [912:680f] | NSImage 0x101b4caf0 大小= {128,128}次数=(

2012-12-31 12:48:52.409 Eicon[912:680f] |NSImage 0x101b4caf0 Size={128, 128} Reps=(

"NSBitmapImageRep 0x10380b900 Size={128, 128} ColorSpace=Generic RGB colorspace BPS=8 BPP=32 Pixels=1024x1024 Alpha=YES Planar=NO

Format = 2 CurrentBacking = | CGImageRef:0x101c14630 | CGImageSource = 0x10380ae70"

Format=2 CurrentBacking=|CGImageRef: 0x101c14630| CGImageSource=0x10380ae70"

)|

2012-12-31 12:48:52.534 Eicon [912:680f] | NSImage 0x101b4caf0 Size = {32, 32}代表=(

2012-12-31 12:48:52.534 Eicon[912:680f] |NSImage 0x101b4caf0 Size={32, 32} Reps=(

"NSBitmapImageRep 0x10380b900 Size={32, 32} ColorSpace=Generic RGB colorspace BPS=8 BPP=32 Pixels=1024x1024 Alpha=YES Planar=NO Format=2

CurrentBacking = | CGImageRef:0x101c14630 | CGImageSource = 0x10380ae70"

CurrentBacking=|CGImageRef: 0x101c14630| CGImageSource=0x10380ae70"

)|

2012-12-31 12:48:52.616 Eicon [912:680f] | NSImage 0x101b4caf0 Size = {32, 32}代表=(

2012-12-31 12:48:52.616 Eicon[912:680f] |NSImage 0x101b4caf0 Size={32, 32} Reps=(

"NSBitmapImageRep 0x10380b900 Size={32, 32} ColorSpace=Generic RGB colorspace BPS=8 BPP=32 Pixels=1024x1024 Alpha=YES Planar=NO Format=2

CurrentBacking = | CGImageRef:0x101c14630 | CGImageSource = 0x10380ae70"

CurrentBacking=|CGImageRef: 0x101c14630| CGImageSource=0x10380ae70"

)|

2012-12-31 12:48:52.729 Eicon [912:680f] | NSImage 0x101b4caf0 Size = {16, 16} Reps =(

2012-12-31 12:48:52.729 Eicon[912:680f] |NSImage 0x101b4caf0 Size={16, 16} Reps=(

"NSBitmapImageRep 0x10380b900 Size={16, 16} ColorSpace=Generic RGB colorspace BPS=8 BPP=32 Pixels=1024x1024 Alpha=YES Planar=NO Format=2

CurrentBacking = | CGImageRef:0x101c14630 | CGImageSource = 0x10380ae70"

CurrentBacking=|CGImageRef: 0x101c14630| CGImageSource=0x10380ae70"

)|

2012-12-31 12:48:52.864 Eicon [912:680f] | NSImage 0x101b4caf0 Size = {16, 16} Reps =(

2012-12-31 12:48:52.864 Eicon[912:680f] |NSImage 0x101b4caf0 Size={16, 16} Reps=(

"NSBitmapImageRep 0x10380b900 Size={16, 16} ColorSpace=Generic RGB colorspace BPS=8 BPP=32 Pixels=1024x1024 Alpha=YES Planar=NO Format=2

CurrentBacking = | CGImageRef:0x101c14630 | CGImageSource = 0x10380ae70"

CurrentBacking=|CGImageRef: 0x101c14630| CGImageSource=0x10380ae70"

)|

推荐答案

错误消息正确.您要放入IconFamily格式不支持的尺寸的图像.具体来说,从您的输出中:

The error message is correct. You're putting in images of a size that is not supported by the IconFamily format. Specifically, from your output:

2012-12-26 13:48:57.682 Eicon [1131:1b0f] | NSImage 0x1025233b0 Size = {11.52,11.52} Reps =("NSBitmapImageRep 0x10421fc30 Size = {11.52, 11.52} ColorSpace =(尚未加载)BPS = 8 BPP =(尚未加载)Pixels = 1024x1024 Alpha = NO Planar = NO Format =(尚未加载)CurrentBacking = nil(故障)CGImageSource = 0x104221170"

2012-12-26 13:48:57.682 Eicon[1131:1b0f] |NSImage 0x1025233b0 Size={11.52, 11.52} Reps=( "NSBitmapImageRep 0x10421fc30 Size={11.52, 11.52} ColorSpace=(not yet loaded) BPS=8 BPP=(not yet loaded) Pixels=1024x1024 Alpha=NO Planar=NO Format=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x104221170"

11.52点对于IconFamily的任何元素而言都不是有效的大小.您需要找出为什么这张图片和代表有那么大的大小.

11.52 points is not a valid size for any element of an IconFamily. You need to find out why this image and rep have that size.

其他一些事情:

  1. 正如我在其他答案中告诉您的那样,您无需更改表示形式的像素大小.不理会像素大小.设置代表和图像的size(点大小)(最好是有效值).
  2. -[NSImage initWithSize:]文档说:

  1. As I told you on that other answer, you don't need to change the pixel size of the representation. Leave the pixel size alone. Set the size (point size) of the rep and image (preferably to something valid).
  2. The -[NSImage initWithSize:] documentation says:

允许通过传递大小(0.0,0.0)来初始化接收器;但是,在使用NSImage对象之前,必须将接收器的大小设置为非零值.否则会引发异常.

It is permissible to initialize the receiver by passing a size of (0.0, 0.0); however, the receiver’s size must be set to a non-zero value before the NSImage object is used or an exception will be raised.

您没有设置任何对象的大小,这是您需要做的. (我很惊讶您没有像文档承诺那样对此有例外.)

You are not setting either object's size, which is what you need to do. (I'm surprised you're not getting an exception about this like the documentation promises.)

正如我在另一个问题上提到的那样,不再有1024点元素; 1024 x 1024像素元素的正确规格为512点@ 2x.这是size(包含图像和表示),为(NSSize){ 512.0, 512.0 }(点),表示为1024 pixelsWide和1024 pixelsHigh.

As I mentioned on your other question, there is no 1024-point element anymore; the correct specification for a 1024-by-1024-pixel element is as 512 points @ 2x. That's a size (of both image and rep) of (NSSize){ 512.0, 512.0 } (points), with the rep being 1024 pixelsWide and 1024 pixelsHigh.

好像我以前缺少一种关键成分.在这里.

Looks like I was missing one key ingredient before. Here it is.

您提供给CGImageDestination的CGImage没有与之关联的磅值-只有NSImages和NSImageReps具有该磅值. CGImage只有一个像素大小;没有任何迹象表明图像的物理尺寸或分辨率.

The CGImage that you give to the CGImageDestination doesn't have a point size associated with it—only NSImages and NSImageReps have that. The CGImage only has a pixel size; nothing to indicate the image's physical size or resolution.

要告诉CGImageDestination给定的CGImage是@ 1x还是@ 2x,您需要创建一个提供图像DPI的字典:

To tell the CGImageDestination whether a given CGImage is meant to be @ 1x or @ 2x, you need to create a dictionary that gives the image's DPI:

NSDictionary *imageProps1x = @{
    (__bridge NSString *)kCGImagePropertyDPIWidth: @72.0,
    (__bridge NSString *)kCGImagePropertyDPIHeight: @72.0,
};
NSDictionary *imageProps2x = @{
    (__bridge NSString *)kCGImagePropertyDPIWidth: @144.0,
    (__bridge NSString *)kCGImagePropertyDPIHeight: @144.0,
};

将正确的字典作为最后一个参数传递给CGImageDestinationAddImage.

Pass the correct dictionary as the last argument to CGImageDestinationAddImage.

这篇关于以编程方式创建ICNS:的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆