1
votes

This code (source is an NSMutableArray with NSImage objects:

NSURL *fileURL = [NSURL fileURLWithPath:aPath];
CGImageDestinationRef dr = CGImageDestinationCreateWithURL((CFURLRef)fileURL,
                                                           kUTTypeAppleICNS,
                                                           1,
                                                           NULL);

for (NSImage *img in source) {

    NSLog(@"%@",img);
    CGImageRef i1 = [img CGImageForProposedRect:NULL context:nil hints:nil];
    CGImageDestinationAddImage(dr, i1, NULL);

}

CGImageDestinationFinalize(dr);
CFRelease(dr);

Resulted in the following 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"

(...) <- here the other NSImage instances are logged.

ImageIO: |ERROR| CGImageDestinationFinalize image destination does not have enough images

Any ideas why it ends with the error at the end? (BTW, I thought of using IconFamily instead but a lot of the methods it uses are deprecated).

EDIT : Maybe it'd be more important to mention the code I use to generate the images, I wouldn't be surprised if that code has problems (I'm a noob) :

// Get images
[source removeAllObjects];
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);
for (int i=0 ; i<10 ; i++) {
    if ([[NSUserDefaults standardUserDefaults] boolForKey:[NSString stringWithFormat:@"Size%i",i+1]]) {
        NSBitmapImageRep *srcimg = [[NSBitmapImageRep alloc] initWithData:[NSData dataWithContentsOfFile:aFile]];
        [srcimg setPixelsHigh:sizes[i].height];
        [srcimg setPixelsWide:sizes[i].width];
        NSImage *newimg = [[NSImage alloc] initWithSize:NSZeroSize];
        [newimg addRepresentation:srcimg];
        if (![newimg isValid]) {
            [delegate error:@"Invalid file."];
        }
        else [source addObject:newimg];
    }
}
2
What if you log your CGImageRef?JWWalker
What does -refFromImage: do? Is it returning something non-nil?paulmelnikow
Please edit your question to include your code for refFromImage:.Peter Hosey
Updated! Not sure how to log a CGImageRef...Fatso
I think you can log a CGImageRef using NSLog, if not use CFShow.JWWalker

2 Answers

3
votes

One part guess at the solution, one part change that will improve the code even if it isn't the solution…

Your number of images in CGImageDestinationCreateWithURL is wrong; you should be passing the number of images you expect to add.

Given a loop, you clearly expect to be adding one or more. Given your output, you are, in fact, adding more than one image.

You said you would add exactly 1 image, and then you added more than one.

My guess is that the error message is unclear/overly specific. The error says:

CGImageDestinationFinalize image destination does not have enough images

But I think what it means is:

CGImageDestinationFinalize image destination has a different number of images than you promised

In other words, the problem isn't that you provided fewer images than expected; it's that you provided more than expected, and CGImageDestination draws no distinction between more and fewer.

Change your CGImageDestinationCreateWithURL call to provide the correct number of images that you'll be adding. Given the code in your question, this should be source.count.

1
votes

Going through -TIFFRepresentation and CGImageSource is highly roundabout. Use the CGImageForProposedRect:context:hints: method instead.