Writing a PNG in C++
Solution 1
LodePNG is as easy as you say. I've used it before as well. Just in case you change your mind and decide to encode the data you have into the right format (assuming it is BGRA
).. The following will convert the BGRA format to RGBA as required by lodepng..
std::vector<std::uint8_t> PngBuffer(ImageData.size());
for(std::int32_t I = 0; I < Height; ++I)
{
for(std::int32_t J = 0; J < Width; ++J)
{
std::size_t OldPos = (Height - I - 1) * (Width * 4) + 4 * J;
std::size_t NewPos = I * (Width * 4) + 4 * J;
PngBuffer[NewPos + 0] = ImageData[OldPos + 2]; //B is offset 2
PngBuffer[NewPos + 1] = ImageData[OldPos + 1]; //G is offset 1
PngBuffer[NewPos + 2] = ImageData[OldPos + 0]; //R is offset 0
PngBuffer[NewPos + 3] = ImageData[OldPos + 3]; //A is offset 3
}
}
std::vector<std::uint8_t> ImageBuffer;
lodepng::encode(ImageBuffer, PngBuffer, Width, Height);
lodepng::save_file(ImageBuffer, "SomeImage.png");
Solution 2
Consider writing your file in NetPBM/PBMplus format as specified here. It is very easy and you don't need a library as the file is so straightforward. The Wikipedia article shows the format here.
Here is a simple example:
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *imageFile;
int x,y,pixel,height=100,width=256;
imageFile=fopen("image.pgm","wb");
if(imageFile==NULL){
perror("ERROR: Cannot open output file");
exit(EXIT_FAILURE);
}
fprintf(imageFile,"P5\n"); // P5 filetype
fprintf(imageFile,"%d %d\n",width,height); // dimensions
fprintf(imageFile,"255\n"); // Max pixel
/* Now write a greyscale ramp */
for(x=0;x<height;x++){
for(y=0;y<width;y++){
pixel=y;
fputc(pixel,imageFile);
}
}
fclose(imageFile);
}
Once you have the file as PBM/PGM frmat, use ImageMagick (here) to convert to PNG with a simple command like:
convert file.pgm file.png
Dan
Updated on March 23, 2020Comments
-
Dan about 4 years
I am trying to write some data to a PNG file using C++ with Visual Studio Express 2013 on Windows 7 64-bit. I understand that to do this, I need to use an external library, but here is where I'm having some difficulty.
I tried using LodePNG - it looked simple, lightweight, and easy to use. The problem is, it was TOO simple, and seems to require data in a certain pixel format that doesn't match what I have. I could modify my data to make it compatible with LodePNG, but I'd much rather use a library such as libpng with a bit more flexibility.
However, I don't understand the first thing about building or linking libraries, and libpng has proved to be an absolute nightmare in this. I tried following this guide, and managed to produce "libpng.lib" and "png.h", but when I try to include these in my project (I placed both files in my project directory, added "png.h" to my header files and added "libpng.lib" to the Linker's "Additional Dependencies" field), I got a ton of build errors, notably:
error C1083: Cannot open include file: 'pnglibconf.h': No such file or directory
Can anyone please instruct me as to how to install libpng, direct me to a good guide on the subject (I'm amazed by the lack of guides out there...), or recommend a different (lightweight, easy to install) PNG library? I'm going crazy here.
-
jiggunjer almost 9 yearsStrange that the lodepng documentation doesn't mention this. It gives the impression that it can load any png supported format.
-
orion elenzil over 2 yearslodepng working super well for my simple use case.