Search code examples
image-processingpnglibpngdeflate

Read and Write png file without change file size in C (libpng)


I want to read the png file, see Image Data and write again without any change in file size. Based on libpng documents,the png is lossless and use deflate and lz77 for compression. There is an example project in libpng which has claimed to read and write image without loss, it's correct in pixel values, but change the structure of file (such as number of IDATs, optional chunks and etc) png file size.

My explicit question: How to extract encode parameters (such as deflate params or lz77 params) from compressed stream (Zstream in libpng) and use this parameters to encode raw image to create image file same as input file without any change?

This is my code. I try to hold params in info_ptr to write image,but not work. How to do it?

int main(int argc, char *argv[])
{
inname = argv[1];
outname = argv[2];

png_structrp read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png_infop info_ptr = png_create_info_struct(read_ptr);



if (!info_ptr)
{
    png_destroy_read_struct(&read_ptr, (png_infopp)NULL, (png_infopp)NULL);
}

png_FILE_p imageFile, imageFile2, imageFileW;
    imageFile=fopen(inname, "rb");  imageFileW = fopen(outname, "wb"); imageFile2 = fopen(inname, "rb");

int fileSize=fsize(imageFile2);
unsigned char* bufImWrite = malloc(sizeof(char)*fileSize);
fread(bufImWrite, 1, fileSize, imageFile2);

png_init_io(read_ptr, imageFile);

png_read_info(read_ptr, info_ptr);


png_uint_32 height;
height = info_ptr->height;


png_bytep * row_pointers;

row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height);
for (int y = 0; y < height; y++)
    row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(read_ptr, info_ptr));


png_read_image(read_ptr, row_pointers);


png_read_end(read_ptr, info_ptr);


png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);;
png_init_io(png_ptr, imageFileW);
png_write_info(png_ptr, info_ptr);
//png_set_compression_level(png_ptr, 9);
//png_set_compression_window_bits(png_ptr, 15);
//png_set_compression_strategy(png_ptr, 3);
//png_set_compression_mem_level(png_ptr, 8);

png_write_image(png_ptr, row_pointers);
png_write_end(png_ptr, info_ptr);


}

Solution

  • In addition to Glenn's correct response, even if you somehow had the parameters used for compression, the compression may have been done by code that is no longer available, or by code that is proprietary and not available to you. In either case there is no way to replicate the exact compressed data. Just keep the original compressed data if you're not going to mess with the image.