【问题标题】:Read and write a PNG file using libpng in C在 C 中使用 libpng 读写 PNG 文件
【发布时间】:2021-04-11 20:12:29
【问题描述】:

我的目标是读取 PNG 文件,更改像素值并使用 libpng 存储更新后的 PNG 文件。

我按照official libpng manual 编写了两个函数,称为read_pngwrite_png。示例代码不会更改像素值,因为它是minimum, reproducible example。它也不会检查输入文件是否实际上是 PNG 文件。

#include <png.h>

png_infop info_ptr;
png_bytepp row_pointers;

void read_png(char *file_name)
{
    FILE *fp = fopen(file_name, "rb");
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    png_infop info_ptr = png_create_info_struct(png_ptr);
    png_init_io(png_ptr, fp);
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
    row_pointers = png_get_rows(png_ptr, info_ptr);
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    fclose(fp);
}

void write_png(char *file_name)
{
    FILE *fp = fopen(file_name, "wb");
    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    png_init_io(png_ptr, fp);
    png_set_rows(png_ptr, info_ptr, row_pointers);
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(fp);
}

int main(int argc, char *argv[])
{
    read_png(argv[1]);
    write_png(argv[2]);
    return 0;
}

代码编译没有任何错误。

$ gcc -o rw_png -lpng rw_png.c

并且程序可以使用两个参数运行。

$ ./rw_png input.png output.png

问题是,虽然 output.png 已创建,但它是一个空文件,而不是 PNG 文件。

$ file output.png
output.png: empty

【问题讨论】:

  • 是时候在调试器中单步调试并找出原因了。

标签: c png libpng


【解决方案1】:

libpng 使用info_struct 来保存有关像素数据外观的信息。所以你需要为write_png 保留它(或重新创建它)。

png_infop info_ptr;  // <-- Global info_ptr (good)
png_bytepp row_pointers; 

void read_png(char *file_name)
{
    FILE *fp = fopen(file_name, "rb");
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    png_infop info_ptr = png_create_info_struct(png_ptr);  // <-- creating a new, local info_ptr 
    png_init_io(png_ptr, fp);
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
    row_pointers = png_get_rows(png_ptr, info_ptr);
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL); // <-- destroying the info_ptr (as well).
    fclose(fp);
}

因此,固定的read_png 将是:

void read_png(char *file_name)
{
    FILE *fp = fopen(file_name, "rb");
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    info_ptr = png_create_info_struct(png_ptr);  
    png_init_io(png_ptr, fp);
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
    row_pointers = png_get_rows(png_ptr, info_ptr);
    png_destroy_read_struct(&png_ptr, NULL, NULL); 
    fclose(fp);
}

假设read_png / write_png,您将在write_png 中释放info_ptr

【讨论】:

    猜你喜欢
    • 2012-04-18
    • 2017-10-29
    • 2012-06-05
    • 2013-08-03
    • 2012-01-11
    • 2017-11-17
    • 2013-11-25
    • 2016-02-24
    相关资源
    最近更新 更多