如何用LIBPNG加载Photoshop png?

时间:2013-02-19 06:47:56

标签: loading libpng

我在加载某些特定的png图像时遇到了一些问题。这是一些有用的图像。

  1. 图片#1 www.silexars.com/image.png(无法正确加载)
  2. 图片#2 www.silexars.com/image2.png(载好)
  3. 使用OpenGL渲染的图像#1的屏幕截图 http://www.silexars.com/screenshot.jpg
  4. 两张图片打开的PNG分析器的屏幕截图: http://www.silexars.com/screenshot.png图片#1 @左,图片#2 @ 右
  5. 我注意到左边的图像有一个名为cHRM的块,我相信我必须以某种方式转换它。 有人会帮我解决这个问题吗?

    我用于加载png文件的代码是:

    uint8 Graphics::Image::loadPNG(FILE *fp) {
    uint8 header[8];
    fread(header,sizeof(header),1,fp);
    if (png_sig_cmp(header,0,sizeof(header))) return INVALID_FILE;
    png_structp png;
    png_infop info;
    
    png = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
    if (!png) return FAILURE;
    info = png_create_info_struct(png);
    if (!info) {
        png_destroy_read_struct(&png,0,0);
        return FAILURE;
    }
    
    png_init_io(png,fp);\
    png_set_sig_bytes(png,sizeof(header));
    
    png_read_info(png,info);
    
    delete[] data;
    data = 0;
    
    int32 bitdepth,colortype;
    png_get_IHDR(png,info,&width,&height,&bitdepth,&colortype,0,0,0);
    
    if (colortype == PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(png);
    }
    if (colortype == PNG_COLOR_TYPE_GRAY && bitdepth < 8) {
        png_set_expand_gray_1_2_4_to_8(png);
    }
    if (colortype == PNG_COLOR_TYPE_GRAY || colortype == PNG_COLOR_TYPE_GRAY_ALPHA) {
        png_set_gray_to_rgb(png);
    }
    if (png_get_valid(png, info, PNG_INFO_tRNS)) {
        png_set_tRNS_to_alpha(png);
    }
    if (colortype == PNG_COLOR_TYPE_RGB) {
        png_set_filler(png, 0xff, PNG_FILLER_AFTER);
    }
    if (bitdepth == 16) {
        png_set_strip_16(png);
    }
    if (bitdepth < 8)
        png_set_packing(png);
    
    png_read_update_info(png,info);
    png_get_IHDR(png,info,&width,&height,0,0,0,0,0);
    
    int32 rowbytes = png_get_rowbytes(png,info);
    
    std::cout << rowbytes/bpp << std::endl;
    
    data = new uint8[rowbytes*height];
    png_bytep *row_pointers = new png_bytep[height*sizeof(png_bytep)];
    for (int i = 0; i < height; i++)
        row_pointers[height-1-i] = data + i * rowbytes;
    
    png_read_image(png, row_pointers);
    
    png_read_end(png,0);
    
    delete[] row_pointers;
    png_destroy_read_struct(&png,&info,0);
    return OK;
    }
    

    希望信息足够。但如果您需要任何额外数据,请问我。

1 个答案:

答案 0 :(得分:1)

第一张图片中的cHRM块与iCCP块中包含的颜色配置文件不一致。最好忽略cHRM块。但是你的代码已经忽略了cHRM和iCCP块。您可以使用png_set_keep_unknown_chunks()来完全忽略它们,以防其中一个导致您看到的麻烦(即使您的代码忽略它们,libpng也会处理它们,除非您使用png_set_keep_unknown_chunks()告诉libpng它们永远不会被处理)。

例如,既然您忽略了应用程序中的所有辅助块,请告诉libpng甚至不要处理它们:

`
    #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
    /* prepare the reader to ignore all recognized chunks whose data won't be
     * used, i.e., all chunks recognized by libpng except for IHDR, PLTE, IDAT,
     * IEND, tRNS, bKGD, gAMA, and sRGB (small performance improvement) */
    {
        /* These byte strings were copied from png.h.  If a future libpng
         * version recognizes more chunks, add them to this list.  If a
         * future version of readpng2.c recognizes more chunks, delete them
         * from this list. */
        static /* const */ png_byte chunks_to_ignore[] = {
             99,  72,  82,  77, '\0',  /* cHRM */
            104,  73,  83,  84, '\0',  /* hIST */
            105,  67,  67,  80, '\0',  /* iCCP */
            105,  84,  88, 116, '\0',  /* iTXt */
            111,  70,  70, 115, '\0',  /* oFFs */
            112,  67,  65,  76, '\0',  /* pCAL */
            112,  72,  89, 115, '\0',  /* pHYs */
            115,  66,  73,  84, '\0',  /* sBIT */
            115,  67,  65,  76, '\0',  /* sCAL */
            115,  80,  76,  84, '\0',  /* sPLT */
            115,  84,  69,  82, '\0',  /* sTER */
            116,  69,  88, 116, '\0',  /* tEXt */
            116,  73,  77,  69, '\0',  /* tIME */
            122,  84,  88, 116, '\0'   /* zTXt */
        };

        png_set_keep_unknown_chunks(png_ptr, 1 /* PNG_HANDLE_CHUNK_NEVER */,
          chunks_to_ignore, sizeof(chunks_to_ignore)/5);
    }
    #endif`

从libpng-1.6.0开始,它更容易。你可以忽略所有 通过输入“-1”除了tRNS块之外的辅助块 在调用中而不是列出要忽略的块:

`
    png_set_keep_unknown_chunks(png,PNG_HANDLE_CHUNK_NEVER, -1, NULL, -1);`

请参阅随libpng for分发的“contrib / gregbook / readpng2.c” 这方面的一个例子。

更新:cHRM块不一定是不一致的。最新版本的ImageMagick报告说它不一致,但这似乎是ImageMagick中的一个错误。同样,使用png_set_keep_unknown_chunks()是个好主意,只是为了避免对你不会使用的辅助块进行不必要的处理。