PNG文件将被截断,无法在每个应用程序中显示

问题描述

我有一个生成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()