Writing a PNG in C++

20,718

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
Share:
20,718
Dan
Author by

Dan

Updated on March 23, 2020

Comments

  • Dan
    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
    jiggunjer almost 9 years
    Strange that the lodepng documentation doesn't mention this. It gives the impression that it can load any png supported format.
  • orion elenzil
    orion elenzil over 2 years
    lodepng working super well for my simple use case.