• 13
• 17
• 27
• 9
• 9

# Trouble with writing png files with libpng

This topic is 4933 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I am working on a png implementation of an image interface in my engine, I have got loading, and very nearly saving to work. The save almost works, its just that its not writing the full color range it seems like. For example, if I had a gradient like this where each box is a pixel:
+---+---+---+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10|
+---+---+---+---+---+---+---+---+---+---+---+

+---+---+---+---+---+---+---+---+---+---+---+
| 10| 9 | 8 | 7 | 6 | 5 | 6 | 7 | 8 | 9 | 10|
+---+---+---+---+---+---+---+---+---+---+---+

I'm not sure if it is exactly half way (127) that this happens with, but it is somewhere near there. I thought I may have figured it out when I discovered png_set_sBIT, but that didn't help. Here is the code I am currently using:
png_structp PngStruct = NULL;
png_infop PngInfo = NULL;
PngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if(!PngStruct)
return false;

PngInfo = png_create_info_struct(PngStruct);
if(!PngInfo)
{
png_destroy_write_struct(&PngStruct, NULL);
return false;
}

png_set_write_fn(PngStruct, &Arc, PngWrite, PngFlush);

png_color_8_struct SigBits;

switch(Format)
{
case ImgA8:
png_set_IHDR(PngStruct, PngInfo, Width, Height, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
SigBits.gray = 8;
png_set_sBIT(PngStruct, PngInfo, &SigBits);
break;
case ImgA16:
png_set_IHDR(PngStruct, PngInfo, Width, Height, 16, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
SigBits.gray = 16;
png_set_sBIT(PngStruct, PngInfo, &SigBits);
break;
case ImgR8G8B8:
png_set_IHDR(PngStruct, PngInfo, Width, Height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
SigBits.red = 8;
SigBits.green = 8;
SigBits.blue = 8;
png_set_sBIT(PngStruct, PngInfo, &SigBits);
break;
case ImgA8R8G8B8:
png_set_IHDR(PngStruct, PngInfo, Width, Height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
SigBits.red = 8;
SigBits.green = 8;
SigBits.blue = 8;
SigBits.alpha = 8;
png_set_sBIT(PngStruct, PngInfo, &SigBits);
break;
default:
png_destroy_write_struct(&PngStruct, &PngInfo);
return false;
}

png_byte ** RowPtrs = new png_byte *[Height];

int Pitch = Width * GetBytesPerPixel();
for(int y = 0; y < Height; ++y)
RowPtrs[y] = &m_ImageData[y * Pitch];

png_set_rows(PngStruct, PngInfo, RowPtrs);

png_write_png(PngStruct, PngInfo, g_PngTransforms, NULL); // g_PngTransforms = PNG_TRANSFORM_BGR | PNG_TRANSFORM_SWAP_ALPHA

png_destroy_write_struct(&PngStruct, &PngInfo);

delete [] RowPtrs;

return true;


I can be relatively sure that the image data is not the problem. I have a base image class, with a couple of different implementations, hopefully this will be one of them soon. Those other implementations don't have the problems that I am talking about when operating on the same data. Anyone that has any experience with libpng maybe hint at what is going on here? I am completely stumped, I've tried all the transformations that seem like they might affect this without any luck. Thanks for any help.

##### Share on other sites
Do you happen to know whether png_byte is a signed or unsigned type?

Do you have code elsewhere which assumes the opposite signed-ness for image data?

##### Share on other sites
Sorry I didn't mention that, png_byte is an unsigned char as is the type of my image data.