libpng png_set_add_alpha | libpng png_set_add_alpha | libpng png_set_filler 错误:连续行溢出
我正在尝试使用 C 读取 PNG 文件以与 OpenCL 一起使用。 OpenCL 不支持 24 位 RGB 图像,因此我需要将数据从 RGB 扩展到 RGBA。我使用的 PNG 都是 24 位的,这样就可以避免头痛。
我尝试使用 png_set_filler 和 png_set_add_alpha 来解决问题,我认为它们大致相同,但它们都会导致此错误:
libpng error: sequential row overflow
这是完整的函数:
int LoadPNG24(unsigned char ** pixelBuffer, const char *filename, unsigned int *width, unsigned int *height) {
png_byte header[8];
//open file as binary
FILE *fp = fopen(filename, "rb");
if (!fp) {
return TEXTURE_LOAD_ERROR;
}
//read the header
fread(header, 1, 8, fp);
//test if png
int is_png = !png_sig_cmp(header, 0, 8);
if (!is_png) {
fclose(fp);
return TEXTURE_LOAD_ERROR;
}
//create png struct
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
fclose(fp);
return (TEXTURE_LOAD_ERROR);
}
//create png info struct
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
fclose(fp);
return (TEXTURE_LOAD_ERROR);
}
//create png info struct
png_infop end_info = png_create_info_struct(png_ptr);
if (!end_info) {
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
fclose(fp);
return (TEXTURE_LOAD_ERROR);
}
//png error stuff, not sure libpng man suggests this.
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return (TEXTURE_LOAD_ERROR);
}
//init png reading
png_init_io(png_ptr, fp);
//let libpng know you already read the first 8 bytes
png_set_sig_bytes(png_ptr, 8);
// read all the info up to the image data
png_read_info(png_ptr, info_ptr);
//variables to pass to get info
int bit_depth, color_type;
png_uint_32 twidth, theight;
// get info about png
png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type, NULL, NULL, NULL);
// Update the png info struct.
png_read_update_info(png_ptr, info_ptr);
// Row size in bytes.
//png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
png_size_t rowbytes = sizeof(png_byte) * 4 * twidth;
// Allocate the image_data as a big block, to be given to opencl
png_byte *image_data = (png_byte *)malloc(sizeof(png_byte) * 4 * twidth * theight);
if (!image_data) {
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return TEXTURE_LOAD_ERROR;
}
//row_pointers is for pointing to image_data for reading the png with libpng
png_bytep *row_pointers = (png_bytep *)malloc(sizeof(png_bytep) * theight);
if (!row_pointers) {
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
free(image_data);
fclose(fp);
return TEXTURE_LOAD_ERROR;
}
// set the individual row_pointers to point at the correct offsets of image_data
for (int i = 0; i < theight; ++i) {
row_pointers[i] = image_data + (i * rowbytes);
}
// PNG Transforms
if (color_type == PNG_COLOR_TYPE_RGB) {
//png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
}
//read the png into image_data through row_pointers
png_read_image(png_ptr, row_pointers);
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
free(row_pointers);
fclose(fp);
//update width and height based on png info
(*pixelBuffer) = image_data;
if (width) {*width = twidth;}
if (height) {*height = theight;}
return TEXTURE_LOAD_OK;
}
谢谢。
I'm trying to read a PNG file with C for use with OpenCL. OpenCL has no support for 24-bit RGB images so I need to expand the data from RGB to RGBA. The PNGs I am using are all 24-bit so that headache can be avoided.
I have attempted to use png_set_filler and png_set_add_alpha which I assume are roughly identical to solve the problem but they both cause this error:
libpng error: sequential row overflow
Here is the function in full:
int LoadPNG24(unsigned char ** pixelBuffer, const char *filename, unsigned int *width, unsigned int *height) {
png_byte header[8];
//open file as binary
FILE *fp = fopen(filename, "rb");
if (!fp) {
return TEXTURE_LOAD_ERROR;
}
//read the header
fread(header, 1, 8, fp);
//test if png
int is_png = !png_sig_cmp(header, 0, 8);
if (!is_png) {
fclose(fp);
return TEXTURE_LOAD_ERROR;
}
//create png struct
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
fclose(fp);
return (TEXTURE_LOAD_ERROR);
}
//create png info struct
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
fclose(fp);
return (TEXTURE_LOAD_ERROR);
}
//create png info struct
png_infop end_info = png_create_info_struct(png_ptr);
if (!end_info) {
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
fclose(fp);
return (TEXTURE_LOAD_ERROR);
}
//png error stuff, not sure libpng man suggests this.
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return (TEXTURE_LOAD_ERROR);
}
//init png reading
png_init_io(png_ptr, fp);
//let libpng know you already read the first 8 bytes
png_set_sig_bytes(png_ptr, 8);
// read all the info up to the image data
png_read_info(png_ptr, info_ptr);
//variables to pass to get info
int bit_depth, color_type;
png_uint_32 twidth, theight;
// get info about png
png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type, NULL, NULL, NULL);
// Update the png info struct.
png_read_update_info(png_ptr, info_ptr);
// Row size in bytes.
//png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
png_size_t rowbytes = sizeof(png_byte) * 4 * twidth;
// Allocate the image_data as a big block, to be given to opencl
png_byte *image_data = (png_byte *)malloc(sizeof(png_byte) * 4 * twidth * theight);
if (!image_data) {
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return TEXTURE_LOAD_ERROR;
}
//row_pointers is for pointing to image_data for reading the png with libpng
png_bytep *row_pointers = (png_bytep *)malloc(sizeof(png_bytep) * theight);
if (!row_pointers) {
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
free(image_data);
fclose(fp);
return TEXTURE_LOAD_ERROR;
}
// set the individual row_pointers to point at the correct offsets of image_data
for (int i = 0; i < theight; ++i) {
row_pointers[i] = image_data + (i * rowbytes);
}
// PNG Transforms
if (color_type == PNG_COLOR_TYPE_RGB) {
//png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
}
//read the png into image_data through row_pointers
png_read_image(png_ptr, row_pointers);
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
free(row_pointers);
fclose(fp);
//update width and height based on png info
(*pixelBuffer) = image_data;
if (width) {*width = twidth;}
if (height) {*height = theight;}
return TEXTURE_LOAD_OK;
}
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好的,更多的谷歌搜索提供了答案。
添加
转换后更新信息指针和行指针并解决问题。
我将答案留在这里,希望能帮助其他人解决这个问题。
Ok, a bit more googling provided the answer.
Adding
After the transformed updated the info ptr and the row pointers and fixed the problem.
I'll leave the answer here in the hopes of helping someone else with this problem.