-
-
Save learosema/013209c4ab5bb3ab3a6ff496e1a016f7 to your computer and use it in GitHub Desktop.
bug fix png encoder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment