Search code examples
c++libpng

Progressive read with libpng: Truncated compressed data in IDAT


I am trying to use the progressive read feature of libpng 1.6.39 (with zlib 1.2.13, GCC/C++ 12, on Linux). However, it seems to not matter what image I try to read, I always end up with the warning

Truncated compressed data in IDAT

and no image data whatsoever.

My code is as follows:

#include "png.h"
#include <unistd.h>
#include <iostream>
#include <iomanip>
#include <cstring>

void errorFn(png_structp png_ptr, png_const_charp error_msg) {
    std::cout << "user_error_fn(): " << error_msg << std::endl;
    _exit(1);
}

void warningFn(png_structp png_ptr, png_const_charp warning_msg) {
    std::cout << "user_warning_fn(): " << warning_msg << std::endl;
}

void infoCallback(png_structp png_ptr, png_infop info) {
    std::cout << "infoCallback()" << std::endl;
}

void rowCallback(png_structp png_ptr, png_bytep new_row, png_uint_32 row_num, int pass) {
    std::cout << "rowCallback(): row_num=" << std::dec << row_num << " pass=" << std::dec << pass << std::endl;
}

void endCallback(png_structp png_ptr, png_infop info) {
    std::cout << "endCallback(): " << std::endl;
}

int main(int argc, char const *argv[]) {
    FILE *fp(fopen("./libpng/1.6.39/contrib/testpngs/rgb-8.png", "rb"));
    std::cout << "fp=" << static_cast<void const *>(fp) << std::endl;
    std::cout << "fseek: " << fseek(fp, 0, SEEK_END) << std::endl;
    size_t const size(ftell(fp));
    std::cout << "ftell: " << size << std::endl;
    fseek(fp, 0, SEEK_SET);
    png_bytep buf(new png_byte[size]);
    memset(buf, 0, size);
    std::cout << "fread: " << fread(buf, 1, size, fp) << std::endl;
    fclose(fp);

    png_structp png_ptr(png_create_read_struct(PNG_LIBPNG_VER_STRING, buf, errorFn, warningFn));
    png_infop info_ptr(png_create_info_struct(png_ptr));

    png_set_progressive_read_fn(png_ptr, buf, infoCallback, rowCallback, endCallback);
    png_process_data(png_ptr, info_ptr, buf, size);


    png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);

    delete[] buf;

    return 0;
}

The file ./libpng/1.6.39/contrib/testpngs/rgb-8.png being read is one of the samples that ships with libpng but I got the same error with every other PNG image I've tried so far and there were quite a few.

I would typically get as output something like this:

fp=0x47eeb0
fseek: 0
ftell: 759
fread: 759
infoCallback()
user_warning_fn(): Truncated compressed data in IDAT
endCallback():

I would have expected a number of calls to my rowCallback() function, and, of course, not getting any warnings (or errors).

Does anybody have any idea what I am doing wrong?


Solution

  • You need to call png_start_read_image() in your infoCallback().