Created — forked from anonymous/pngencode.cpp

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

bug fix png encoder

View pngencode.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
// by alex evans, 2011. released into the public domain.
// based on a first ever reading of the png spec, it occurs to me that a minimal png encoder should be quite simple.
// this is a first stab - may be buggy! the only external dependency is zlib and some basic typedefs (u32, u8)
//
// VERSION 0.02! now using zlib's crc rather than my own, and avoiding a memcpy and memory scribbler in the old one
// by passing the zero byte at the start of the scanline to zlib first, then the original scanline in place. WIN!
//
// more context at http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
//
// follow me on twitter @mmalex http://twitter.com/mmalex
//
u8* CompressPNG(void *img, int w, int h, int numchans, u32 &len_out) {
int p=w*numchans;
z_stream z={0};
deflateInit(&z,-1);
u8 *zbuf=(u8*)malloc(53+(z.avail_out=deflateBound(&z,(1+p)*h))+1);
if (!zbuf) return 0;
z.next_out=zbuf+41;
for (int y=0;y<h;++y) {
Bytef zero=0; z.avail_in=1;z.next_in=&zero; deflate(&z,Z_NO_FLUSH);
z.avail_in=p;z.next_in=((Bytef*)img)+y*p; deflate(&z,(y==h-1) ? Z_FINISH : Z_NO_FLUSH);
}
len_out=z.next_out-zbuf-41;
u8 pnghdr[41]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
0,0,w>>8,w,0,0,h>>8,h,8,"\0\0\04\02\06"[numchans],0,0,0,0,0,0,0,
len_out>>24,len_out>>16,len_out>>8,len_out,0x49,0x44,0x41,0x54};
*(u32*)(pnghdr+29)=htonl(crc32(0,pnghdr+12,17));
memcpy(zbuf,pnghdr,41);
memcpy(z.next_out+4,"\x49\x45\x4e\x44\xae\x42\x60\x82",8); // footer
*(u32*)z.next_out =htonl(crc32(0, zbuf+41-4, len_out+4));
deflateEnd(&z); len_out+=53; return zbuf;
}
void PNGTest()
{
u32 img[200][320];
for (int y=0;y<200;++y) for (int x=0;x<320;++x) img[y][x]=x+(y<<8)+0xff000000;
u32 blen; u8*zbuf = CompressPNG(img,16,16,4,blen);
FILE *f=fopen("test.png","wb");
fwrite(zbuf,1,blen,f);
fclose(f);
free(zbuf);
}

A modified version of this function is used by miniz.c : https://code.google.com/p/miniz/issues/entry

To except pre-filter image data, add a byte array of filter types (length h):

line 12: add parameter "u8 *filters"
line 20: replace z.next_in=&zero; with z.next_in=filters ? filters+y : &zero;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.