代码之家  ›  专栏  ›  技术社区  ›  Tom

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

  •  4
  • Tom  · 技术社区  · 14 年前

    我对在iPhone应用程序中加载索引的彩色PNG图像很感兴趣。一旦它们被加载,我想以每像素为基础访问图像。特别是,我想得到单个像素的颜色索引(而不是颜色本身)。

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

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

    事先谢谢!

    更新:我可以使用quartz2d加载png,但出于某种原因,它会自动将索引颜色8bit png转换为32位argb png。有没有想过我该如何预防?

    更新2:这一点很重要的原因是由于内存限制。我试图防止光栅从每像素8位放大到32位,以避免开销。如果有人能给我一个神奇的答案,100分就是你的了!

    1 回复  |  直到 10 年前
        1
  •  7
  •   mvds    14 年前

    通过将图像加载为cgImage而不是uiImage,使用cgImageCreateWithPngDataProvider(),您可能能够获得索引颜色空间。见:

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

    其中列出了cgcolorspaceCreateIndexed()、cgcolorspaceGetColorTable()等。使用cgColorSpaceGetModel(cgImageGetColorSpace(img))查看最终使用的颜色空间是否为索引空间,然后使用cgImageGetDataProvider()获取cgDataProviderRef,可以使用cgDataProviderPyData()获取实际位图数据…

    编辑 赏金总能使事情顺利进行。我做了测试,结果很好。(不好意思处理得很糟糕,这当然是概念证明)

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

    结果在我的案例中(b/w图像)

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

    编辑^ 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");
    }