iPhone SDK:访问索引彩色 PNG 图像

发布于 2024-09-09 04:30:07 字数 405 浏览 0 评论 0原文

我有兴趣在我的 iPhone 应用程序中加载索引颜色 PNG 图像。加载后,我想按像素访问图像。特别是,我想获取各个像素的颜色索引(而不是颜色本身)。

不幸的是,似乎没有办法通过 UIImage 类访问像素,更不用说像素的颜色索引了。我也在研究 Quartz2D 相关的 API,但到目前为止,情况看起来很黯淡。

我将非常感谢任何建议。 我希望我不必从 libpng 移植必要的代码。

提前致谢!

更新:我可以使用 Quartz2D 加载 PNG,但由于某种原因,它会自动将我的索引颜色 8 位 PNG 转换为 32 位 ARGB PNG。我有什么想法可以防止这种情况发生吗?

更新 2:这很重要的原因是由于内存限制。我试图防止光栅从每像素八位扩展到三十二位,以避免开销。如果有人对我有神奇的答案,100分就是你的!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

晨敛清荷 2024-09-16 04:30:07

通过使用 CGImageCreateWithPNGDataProvider() 将图像加载为 CGImage 而不是 UIImage,您也许能够获得索引颜色空间。请参阅:

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

其中列出了 CGColorSpaceCreateIndexed()、CGColorSpaceGetColorTable() 等。使用 CGColorSpaceGetModel(CGImageGetColorSpace(img)) 查看最终获得的颜色空间是否是索引颜色空间,然后使用 CGImageGetDataProvider() 获取 CGDataProviderRef,您可以将其与 CGDataProviderCopyData() 一起使用来获取实际的位图数据。

编辑赏金总是能让事情顺利进行。我测试过,它确实有效。 (对于糟糕的处理感到抱歉,这当然是概念验证)

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

输出:

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

qed?

附:我的测试图像来自 libgd,通过 php,使用

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

它在 edit^2 中生成我的情况(黑白图像),

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

这就是访问位图数据的方式。 ASCII 艺术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");
}

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");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文