Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
392 views
in Technique[技术] by (71.8m points)

objective c - 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 avoid the overhead. If anyone has the magic answer for me, 100 points are yours!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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
",[path UTF8String]);
NSData *file = [[NSFileManager defaultManager] contentsAtPath:path];
if ( !file ) printf("file failed
");
CGDataProviderRef src = CGDataProviderCreateWithCFData(file);
if ( !src ) printf("image failed
");
CGImageRef img = CGImageCreateWithPNGDataProvider(src, NULL, NO, kCGRenderingIntentDefault);
if ( !img ) printf("image failed
");

printf("Color space model: %d, indexed=%d
",
    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
");
[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
",w,bpl,h,bpl*h,[nsdata length]);

if ( [nsdata length] != bpl*h )
{
    printf("%d pixels is not %d bytes, i may be crashing now...
",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("
");
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...