开发者

iPhone SDK: accessing indexed color PNG images

I'm interested in loading indexed-color PNG images in my iPhone application. Once they're loaded, I want to access the images on a per-pixel basis. In particular, I want to get the index of the color (rather than the color itself) of individual pixels.

Unfortunately, there does not seem to be a way to access pixels via the UIImage class, let alone color index of a pixel. I'm also taking a look at Quartz2D-related APIs, but so far things look bleak.

I'd greatly appreciate any suggestions. I'm hoping I won't have to port the necessary code from libpng.

Thanks in advance!

UPDATE: I'm able to load the PNG using Quartz2D, but for some reason it automatically converts my indexed-color 8bit PNG to a 32-bit ARGB PNG. Any thoughts how I might prevent this?

UPDATE 2: The reason this is important is due to memory limitations. I'm trying to keep the raster from blowing up form eight bits per pixel to thirty two to av开发者_StackOverflowoid the overhead. If anyone has the magic answer for me, 100 points are yours!


By loading the image as a CGImage rather than an UIImage, using CGImageCreateWithPNGDataProvider(), you might be able to get an indexed color space. See:

http://developer.apple.com/iphone/library/documentation/GraphicsImaging/Reference/CGColorSpace/Reference/reference.html

which lists CGColorSpaceCreateIndexed(), CGColorSpaceGetColorTable() and more. Use CGColorSpaceGetModel(CGImageGetColorSpace(img)) to see if the color space you end up with is an indexed one, then use CGImageGetDataProvider() to get a CGDataProviderRef, which you can use with CGDataProviderCopyData() to get to the actual bitmap data...

edit a bounty always gets things going. I tested and it just works. (sorry for the crappy handling, this is proof of concept of course)

NSString *path = [[[NSBundle mainBundle] resourcePath] 
            stringByAppendingPathComponent:@"test.png"];
printf("path: %s\n",[path UTF8String]);
NSData *file = [[NSFileManager defaultManager] contentsAtPath:path];
if ( !file ) printf("file failed\n");
CGDataProviderRef src = CGDataProviderCreateWithCFData(file);
if ( !src ) printf("image failed\n");
CGImageRef img = CGImageCreateWithPNGDataProvider(src, NULL, NO, kCGRenderingIntentDefault);
if ( !img ) printf("image failed\n");

printf("Color space model: %d, indexed=%d\n",
    CGColorSpaceGetModel(CGImageGetColorSpace(img)),
    kCGColorSpaceModelIndexed);

output:

path: /Users/..../638...8C12/test.app/test.png
Color space model: 5, indexed=5

qed?

ps. my test image is from libgd, through php, using

    $img = imagecreatefrompng("whateverimage.png");
    imagetruecolortopalette($img,false,256);
    header("Content-Type: image/png");
    imagepng($img);

which results in my case (b/w image) in

$ file test.png 
test.png: PNG image, 2000 x 300, 1-bit colormap, non-interlaced

edit^2 This is how you access the bitmap data. ASCII art ftw!

CGDataProviderRef data = CGImageGetDataProvider(img);
NSData *nsdata = (NSData *)(CGDataProviderCopyData(data));

char *rawbuf = malloc([nsdata length]);
if ( !rawbuf ) printf("rawbuf failed\n");
[nsdata getBytes:rawbuf];

int w = CGImageGetWidth(img);
int h = CGImageGetHeight(img);
int bpl = CGImageGetBytesPerRow(img);

printf("width: %d (%d bpl), height: %d, pixels: %d, bytes: %d\n",w,bpl,h,bpl*h,[nsdata length]);

if ( [nsdata length] != bpl*h )
{
    printf("%d pixels is not %d bytes, i may be crashing now...\n",bpl*h,[nsdata length]);
}

for ( int y=0;y<h; y++ )
{
    for ( int x=0;x<w; x++ )
    {
        char c = rawbuf[y*bpl+x];
        while ( !isalnum(c) ) c += 31; //whoa!
        printf("%c",c);
    }
    printf("\n");
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜