Skip to content

Instantly share code, notes, and snippets.

@linuxenko
Forked from fpsunflower/nanopng.cpp
Created November 19, 2016 08:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save linuxenko/35213f65e2cb8568754ce5d3d9bbea99 to your computer and use it in GitHub Desktop.
Save linuxenko/35213f65e2cb8568754ce5d3d9bbea99 to your computer and use it in GitHub Desktop.
Tiny PNG output
// c++ -o nanopng nanopng.cpp && ./nanopng /tmp/foo.png
#include <cstdio>
// write an uncompressed PNG file from a uint8 RGB buffer
struct Png {
FILE*f; unsigned int tab[256], crc; ~Png() { fclose(f); }
Png(const char* fn, int w, int h, const unsigned char* c) {
crc=0x575e51f5;unsigned char d[]={137,80,78,71,13,
10,26,10,0,0,0,13,73,72,68,82,73,68,65,84,120,1,0,
0,0,73,69,78,68,174,66,96,130};/*chunk headers*/
for (int i=0;i<256;i++)/*precompute crc tables*/
for (unsigned int j=8,&v=tab[i]=i;j--;)
v=(v>>1)^(0xedb88320u&(~(v&1)+1));
fwrite(d,1,16,f=fopen(fn,"w")); /*write IHDR+IDAT*/
*this>>w>>h<<8<<2<<0<<0<<0;int a=1,b=0;/*adler-32*/
*this>>~crc>>(h*(w*3+6)+6);int len=w*3+1;/*nbytes*/
fwrite(d+16,1,6,f);crc=0x13e5812d;
for (;h--;) {/*DEFLATE raw block*/
*this<<!h<<len<<(len>>8)<<~len<<(~len>>8);
/*filter=0*/*this <<0;/*adler(0)*/b=(a+b)%65521;
for (int x=w,v;x--;){ /*write & checksum*/
v=*c++;*this<<v;a=(a+v)%65521;b=(a+b)%65521;
v=*c++;*this<<v;a=(a+v)%65521;b=(a+b)%65521;
v=*c++;*this<<v;a=(a+v)%65521;b=(a+b)%65521;
}
}
*this>>((b<<16)|a);*this>>~crc;fwrite(d+22,1,12,f);
}
Png& operator<<(int b){crc=(crc>>8)^tab[(crc^fputc(b,f))&255];return *this;}
Png& operator>>(unsigned int v) {return *this<<(v>>24)<<(v>>16)<<(v>>8)<<v;}
};
// example usage
int main(int argc, const char** argv) {
int w = 640, h = 480;
unsigned char* image = new unsigned char[3 * w * h];
for (int y = 0, idx = 0; y < h; y++)
for (int x = 0; x < w; x++, idx += 3)
image[idx + 0] = (255 * x) / w,
image[idx + 1] = (255 * y) / h,
image[idx + 2] = 0;
Png(argc < 2 ? "/tmp/test.png" : argv[1], w, h, image);
delete [] image;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment