【问题标题】:iPhone SDK: accessing indexed color PNG imagesiPhone SDK:访问索引颜色 PNG 图像
【发布时间】:2011-03-16 03:52:22
【问题描述】:

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

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

如果有任何建议,我将不胜感激。 我希望我不必从 libpng 移植必要的代码。

提前致谢!

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

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

【问题讨论】:

  • 你能分享一张这样的图片让我们稍微修改一下吗?

标签: iphone objective-c png


【解决方案1】:

通过使用 CGImageCreateWithPNGDataProvider() 将图像加载为 CGImage 而不是 UIImage,您可能可以获得索引颜色空间。见:

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

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

edit赏金总是能让事情顺利进行。我测试过,它只是工作。 (对不起,糟糕的处理,这当然是概念证明)

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?

ps。我的测试图像来自 libgd,通过 php,使用

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

这导致我的情况(黑白图像)

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

edit^2 这是您访问位图数据的方式。 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");
}

【讨论】:

  • 谢谢,这绝对给了我一些想法。不幸的是,到目前为止,我只能让 CGImageCreateWithPNGDataProvider() 给我一个 RGB 颜色空间图像。也许它正在进行某种转换,因为我碰巧知道该图像已经是索引颜色的图像。
  • 您是否在编译步骤中执行“压缩 PNG”?这会将您的 PNG 转换为 RGB 图像。如果您依赖 PNG 格式,请确保将其关闭。
  • 添加了获取像素缓冲区的示例。
  • 注意:该示例假定每像素 8 位,而 1 位索引颜色存储为每像素 1 位,因此每字节 8 像素。
  • @Tom:您能尝试从 1 位颜色图开始并复制我的结果吗?然后增加数字颜色,看看转折点在哪里。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-25
  • 2019-04-06
相关资源
最近更新 更多