问题描述
我有一个生成PNG文件的代码(使用libpng)。 我可以使用EOG(Eye Of Gnome)打开这些文件,但是使用GIMP,imagemagic和其他文件时我出错。 Exiftool告诉我png文件被截断了,但是我看不到哪里。在EOG上一切正常。
代码:
int savepng(const char *name,fits *fit,uint32_t bytes_per_sample,gboolean is_colour) {
int32_t ret = -1;
png_structp png_ptr;
png_infop info_ptr;
const uint32_t width = fit->rx;
const uint32_t height = fit->ry;
char *filename = strdup(name);
if (!ends_with(filename,".png")) {
filename = str_append(&filename,".png");
}
FILE *p_png_file = g_fopen(name,"wb");
if (p_png_file == NULL) {
return ret;
}
/* Create and initialize the png_struct with the desired error handler
* functions. If you want to use the default stderr and longjump method,* you can supply NULL for the last three parameters. We also check that
* the library version is compatible with the one used at compile time,* in case we are using dynamically linked libraries. required.
*/
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL);
if (png_ptr == NULL) {
fclose(p_png_file);
return ret;
}
/* Allocate/initialize the image information data. required */
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
fclose(p_png_file);
png_destroy_write_struct(&png_ptr,NULL);
return ret;
}
/* Set error handling. required if you aren't supplying your own
* error handling functions in the png_create_write_struct() call.
*/
if (setjmp(png_jmpbuf(png_ptr))) {
/* If we get here,we had a problem writing the file */
fclose(p_png_file);
png_destroy_write_struct(&png_ptr,&info_ptr);
return ret;
}
/* Set up the output control if you are using standard C streams */
png_init_io(png_ptr,p_png_file);
/* Set the image information here. Width and height are up to 2^31,* bit_depth is one of 1,2,4,8,or 16,but valid values also depend on
* the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,* PNG_COLOR_TYPE_GRAY_ALPHA,PNG_COLOR_TYPE_PALETTE,PNG_COLOR_TYPE_RGB,* or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
* PNG_INTERLACE_Adam7,and the compression_type and filter_type MUST
* currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. required
*/
if (is_colour) {
png_set_IHDR(png_ptr,info_ptr,width,height,bytes_per_sample * 8,PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_BASE,PNG_FILTER_TYPE_DEFAULT);
uint32_t profile_len;
const unsigned char *profile = get_sRGB_profile_data(&profile_len);
if (profile_len > 0) {
png_set_iCCP(png_ptr,*name ? name : "icc",(png_const_bytep) profile,profile_len);
}
} else {
png_set_IHDR(png_ptr,PNG_COLOR_TYPE_GRAY,PNG_FILTER_TYPE_DEFAULT);
}
/* Write the file header information. required */
png_write_info(png_ptr,info_ptr);
png_bytep *row_pointers = malloc((size_t) height * sizeof(png_bytep));
int samples_per_pixel;
if (is_colour) {
samples_per_pixel = 3;
} else {
samples_per_pixel = 1;
}
if (bytes_per_sample == 2) {
/* swap bytes of 16 bit files to most significant bit first */
png_set_swap(png_ptr);
WORD *data = convert_data(fit);
for (unsigned i = 0,j = height - 1; i < height; i++)
row_pointers[j--] = (png_bytep) ((uint16_t*) data + (size_t) samples_per_pixel * i * width);
} else {
uint8_t *data = convert_data8(fit);
for (unsigned i = 0,j = height - 1; i < height; i++)
row_pointers[j--] = (uint8_t*) data + (size_t) samples_per_pixel * i * width;
}
png_write_image(png_ptr,row_pointers);
/* Clean up after the write,and free any memory allocated */
png_destroy_write_struct(&png_ptr,&info_ptr);
/* Close the file */
fclose(p_png_file);
free(row_pointers);
free(filename);
return 0;
}
有人可以指出我的错误吗?无法读取图像的软件只会显示一个错误对话框。就这样。因此,我很难知道错误在哪里。
解决方法
如@MarkSetchell所建议,缺少一行:
/* Clean up after the write,and free any memory allocated */
png_write_end(png_ptr,info_ptr); // this line was missing
png_destroy_write_struct(&png_ptr,&info_ptr);
仅此而已。
谢谢。
,我认为go get github.com/VonC/gtarsum
仅写入图像行数据,因此缺少各种标头或元数据元素。我通常使用png_write_image()
写入整个文件。
我已经附加了一些绝对适合我的代码,因为输出可以由Gimp读取,等等。我不认为这是生产质量;)
png_write_png()