以编程方式创建ICNS:“不支持的图像大小” [英] Creating an ICNS Programmatically : "Unsupported Image Size"

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

问题描述

我正在尝试以编程方式创建ICNS(包括1024x1024图片)。目前我创建一个 NSImage ,然后创建 CGImageRef 对象与相应的分辨率,最后我添加它们使用 CGImageDestinationAddImage()更改为图标。 Peter Hosey帮助我创建了@ 2x图片,但图片的尺寸不想设置。



这是代码仍然有点乱, sourcefile 表示图像的路径):

  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];

//创建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]]){

//创建字典
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 representation])[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);

//添加图片
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 当前图像应该是。 dpi 是144,如果我们创建一个@ 2x图片,否则为72.这些值已通过 NSLog



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


ImageIO:_CGImagePluginWriteICNS不支持的图片大小(1024 x 1024) 1


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



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






编辑:我记录了图片:


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

 NSBitmapImageRep 0x10380b900 Size = {512,512} ColorSpace =(尚未加载)BPS = 8 BPP =(尚未加载)像素= 1024x1024 Alpha = YES 

Planar = NO格式=(尚未加载)CurrentBacking = nil(faulting)
CGImageSource = 0x10380ae70





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

 NSBitmapImageRep 0x10380b900 Size = {512,512} ColorSpace =通用RGB色彩空间BPS = 8 BPP = 32像素= 1024x1024 Alpha = = NO 

格式= 2 CurrentBacking = | CGImageRef:0x101c14630 |
CGImageSource = 0x10380ae70



)|



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

 NSBitmapImageRep 0x10380b900 Size = {256,256} ColorSpace =通用RGB色彩空间BPS = 8 BPP = 32像素= 1024x1024 Alpha = YES平面= NO 


b $ b

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



)|



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

 NSBitmapImageRep 0x10380b900 Size = {256,256} ColorSpace =通用RGB色彩空间BPS = 8 BPP = 32像素= 1024x1024 Alpha = YES平面= NO 

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



)|



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 

格式= 2 CurrentBacking = | CGImageRef:0x101c14630 |
CGImageSource = 0x10380ae70



)|



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

 NSBitmapImageRep 0x10380b900 Size = {128,128} ColorSpace =通用RGB色彩空间BPS = 8 BPP = 32像素= 1024x1024 Alpha = YES平面= NO 


b $ b

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



)|



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

 NSBitmapImageRep 0x10380b900 Size = {32,32} ColorSpace =通用RGB颜色空间BPS = 8 BPP = 32像素= 1024x1024 Alpha = YES Planar = NO格式= 2 

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



)|



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

 NSBitmapImageRep 0x10380b900 Size = {32,32} ColorSpace =通用RGB色彩空间BPS = 8 BPP = 32像素= 1024x1024 Alpha = YES Planar = NO Format = 2 

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



)|



2012-12-31 12:48:52.729 Eicon [ 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



)|



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

 code>NSBitmapImageRep 0x10380b900 Size = {16,16} ColorSpace =通用RGB颜色空间BPS = 8 BPP = 32像素= 1024x1024 Alpha = YES Planar = NO格式= 2 
/ pre>

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



)|



解决方案

错误讯息正确。您输入的图片尺寸不受IconFamily支持格式。具体来说,从您的输出:


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 = 1024x1024 Alpha = NO Planar = NO格式=(尚未载入)CurrentBacking = nil(faulting)CGImageSource = 0x104221170


11.52分



还有一些其他的东西:


  1. 正如我在其他答案中所说的,你不需要改变表示的像素大小, c> c> c>

    - [NSImage initWithSize:] 文档说:


    允许通过传递一个大小(0.0,0.0);但是,在使用NSImage对象或者引发异常之前,接收器的大小必须设置为非零值。


    你不是设置任何对象的大小,这是你需要做的。 (我很惊讶你没有像这样的文档承诺有异常。)


对你的另一个问题,没有1024点元素了;对于1024乘1024像素的元素的正确规范是512点@ 2x。这是(NSSize){512.0,512.0} (点)的 size 代表为1024 pixelsWide 和1024 pixelsHigh






看起来我之前缺少一个关键成分。这是它。



您给予CGImageDestination的CGImage没有与其关联的点大小,因为只有NSImages和NSImageReps。 CGImage只有一个像素大小;



要告诉CGImageDestination给定的CGImage是@ 1x还是@ 2x,您需要创建一个字典给出图像的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


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.

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 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.

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 unsupported image size (1024 x 1024) - scaling factor: 1

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

I need to know how to set the size of the CGImage that is to be added to the ICNS file.


EDIT : I logged the images :

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=(not yet loaded) CurrentBacking=nil (faulting) CGImageSource=0x10380ae70"

)|

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"

)|

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"

)|

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"

)|

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"

)|

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"

)|

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"

)|

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"

)|

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"

)|

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"

)|

解决方案

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=(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 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.

A couple of other things:

  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:

    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.)

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.

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.

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,
};

Pass the correct dictionary as the last argument to CGImageDestinationAddImage.

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

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