Hello. I load textures from 24bit RGB png files using libpng.
The problem is that it reads pngs made in one pc’s Paint (Win10), but fails to read pngs made in another pc’s Paint (Win10), although the format is 24 bit on each png.
Error is: “An invalid parameter was passed to a function that considers invalid parameters fatal.” in png_default_read_data(). Why?
The program fails at png_read_image(png_ptr, row_pointers);
The color and bit depth are the same for these two pcs’ png files.
Here is the libpng code:
int width, height;
for (int j = 0; j < materials.size(); ++j)
{
//header for testing if it is a png
png_byte header[8];
FILE *fp;
errno_t err;
if ((err = fopen_s(&fp,
(object_root+materials[j].texture_name).c_str(), "rb")) != 0)
{
OutputDebugStringA("Faulire to open a png file.");
exit(EXIT_FAILURE);
}
//read the header
fread(header, 1, 8, fp);
//test if png
int is_png = !png_sig_cmp(header, 0, 8);
if (!is_png)
{
fclose(fp);
OutputDebugStringA("File is not of png format.");
exit(EXIT_FAILURE);
}
//create png struct
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
NULL, NULL);
if (!png_ptr)
{
fclose(fp);
OutputDebugStringA("Failure to create a png struct.");
exit(EXIT_FAILURE);
}
//create png info struct
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
fclose(fp);
OutputDebugStringA("Faulire to create a png info struct.");
exit(EXIT_FAILURE);
}
//create png info struct
png_infop end_info = png_create_info_struct(png_ptr);
if (!end_info)
{
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
fclose(fp);
OutputDebugStringA("Faulire to create a png info struct.");
exit(EXIT_FAILURE);
}
//png error stuff, not sure libpng man suggests this.
if (setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
OutputDebugStringA("Faulire to set png error stuff.");
exit(EXIT_FAILURE);
}
//init png reading
png_init_io(png_ptr, fp);
//let libpng know you already read the first 8 bytes
png_set_sig_bytes(png_ptr, 8);
// read all the info up to the image data
png_read_info(png_ptr, info_ptr);
//variables to pass to get info
int bit_depth, color_type;
png_uint_32 twidth, theight;
// get info about png
png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type,
NULL, NULL, NULL);
//update width and height based on png info
width = twidth;
height = theight;
png_byte filler = 255;
if (color_type != PNG_COLOR_TYPE_RGB_ALPHA)
{
if (color_type == PNG_COLOR_TYPE_RGB)
{
png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER);
}
else
{
OutputDebugStringA("Not RGB png.");
exit(EXIT_FAILURE);
}
}
else
{
OutputDebugStringA("Not RGB png.");
exit(EXIT_FAILURE);
}
// Update the png info struct.
png_read_update_info(png_ptr, info_ptr);
// Row size in bytes.
int rowbytes = (int)png_get_rowbytes(png_ptr, info_ptr);;
// Allocate the image_data as a big block, to be given to opengl
png_byte *image_data = new png_byte[rowbytes * height];
if (!image_data)
{
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
OutputDebugStringA("Faulire to allocate the image data as a big block.");
exit(EXIT_FAILURE);
}
//row_pointers is for pointing to image_data for reading the png with libpng
png_bytep *row_pointers = new png_bytep[height];
if (!row_pointers)
{
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete[] image_data;
fclose(fp);
OutputDebugStringA("Faulire to allocate row pointers.");
exit(EXIT_FAILURE);
}
// set the individual row_pointers to point at the correct offsets of image_data
for (int i = 0; i < height; ++i)
{
row_pointers[height - 1 - i] = image_data + i * rowbytes;
}
//read the png into image_data through row_pointers
png_read_image(png_ptr, row_pointers);
if (j == 0)
{
glTexStorage3D(GL_TEXTURE_2D_ARRAY, mipLevelCount,
GL_RGBA8, width, height, (GLsizei)materials.size());
}
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, j, width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)image_data);
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete[] image_data;
delete[] row_pointers;
fclose(fp);
}