iPhone: Changing CGImageAlphaInfo of CGImage
Asked Answered
G

2

26

I have a PNG image that has an unsupported bitmap graphics context pixel format. Whenever I attempt to resize the image, CGBitmapContextCreate() chokes on the unsupported format

I receive the following error (error formatted for easy reading):

CGBitmapContextCreate: unsupported parameter combination: 
    8 integer bits/component; 
    32 bits/pixel; 
    3-component colorspace; 
    kCGImageAlphaLast; 
    1344 bytes/row.

The list of supported pixel formats definitely does not support this combination. It appears I need to redraw the image and move the alpha channel information to kCGImageAlphaPremultipliedFirst or kCGImageAlphaPremultipliedLast.

I have no idea how to go about doing this.

There is nothing unusual about the PNG file and it isn't corrupted. It works in all other context just fine. I encountered this error just by chance but obviously my users might have similarly formatted files so I will have to check my app's imported images and correct for this problem.

Gradualism answered 16/3, 2010 at 18:37 Comment(0)
S
59

Yeah, I had problems with 8 bit (indexed) .PNGs. I had to convert it to a more native image to perform graphics operations. I essentially did something like this:

- (UIImage *) normalize {

    CGColorSpaceRef genericColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef thumbBitmapCtxt = CGBitmapContextCreate(NULL, 
                                                         self.size.width, 
                                                         self.size.height, 
                                                         8, (4 * self.size.width), 
                                                         genericColorSpace, 
                                                         kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(genericColorSpace);
    CGContextSetInterpolationQuality(thumbBitmapCtxt, kCGInterpolationDefault);
    CGRect destRect = CGRectMake(0, 0, self.size.width, self.size.height);
    CGContextDrawImage(thumbBitmapCtxt, destRect, self.CGImage);
    CGImageRef tmpThumbImage = CGBitmapContextCreateImage(thumbBitmapCtxt);
    CGContextRelease(thumbBitmapCtxt);    
    UIImage *result = [UIImage imageWithCGImage:tmpThumbImage];
    CGImageRelease(tmpThumbImage);

    return result;    
}
Saiva answered 20/3, 2010 at 21:48 Comment(6)
Looks good, I'll try it. I'm loathe to do to much processing because I'm afraid I'll inadvertently destroy fidelity.Gradualism
I finally got around to testing this and it works fine with no discernible loss of fidelity.Gradualism
I am having an issue with the above code when the imageOrientation of the UIImage is anything but OrientationUp - this causes the image to be rotated. The bounds of the image stay the same, but the pixels inside the image are rotated and stretched to fit the original bounds. This is similar to what is described in: #5973605 but in this case it's the normalize function that appears to be causing the issue. Anyone else see this? Any fix for this?Syriac
The code does not assume anything about orientation: Orientation information is not stored in a UIImage. (You should handle orientation before converting an image to a UIImage.)Saiva
see my answer to this question #5546100Pedi
This produces much better results than the method I was using, thanks.Virginavirginal
C
5

Here's an updated version of the method from Alfons answer to account for screen scale, and also some silly errors with decimals in floating point values of the image size as described in unsynchronized's comment from the original answer.

SCREEN_SCALE is a macro that returns either 1.0 if scale isn't defined or whatever the device scale actually is ([UIScreen mainScreen].scale).

- (UIImage *) normalize {

    CGSize size = CGSizeMake(round(self.size.width*SCREEN_SCALE), round(self.size.height*SCREEN_SCALE));
    CGColorSpaceRef genericColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef thumbBitmapCtxt = CGBitmapContextCreate(NULL, 
                                                         size.width, 
                                                         size.height, 
                                                         8, (4 * size.width), 
                                                         genericColorSpace, 
                                                         kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(genericColorSpace);
    CGContextSetInterpolationQuality(thumbBitmapCtxt, kCGInterpolationDefault);
    CGRect destRect = CGRectMake(0, 0, size.width, size.height);
    CGContextDrawImage(thumbBitmapCtxt, destRect, self.CGImage);
    CGImageRef tmpThumbImage = CGBitmapContextCreateImage(thumbBitmapCtxt);
    CGContextRelease(thumbBitmapCtxt);    
    UIImage *result = [UIImage imageWithCGImage:tmpThumbImage scale:SCREEN_SCALE orientation:UIImageOrientationUp];
    CGImageRelease(tmpThumbImage);

    return result;    
}
Cari answered 20/2, 2012 at 22:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.