我在加载某些特定的png图像时遇到了一些问题。这是一些有用的图像。
我注意到左边的图像有一个名为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;
}
希望信息足够。但如果您需要任何额外数据,请问我。
答案 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()是个好主意,只是为了避免对你不会使用的辅助块进行不必要的处理。