int MDFN_SavePNGSnapshot(const char *fname, uint32 *fb, const MDFN_Rect *rect, uint32 pitch) { int x, y; FILE *pp=NULL; uint8 *compmem = NULL; uLongf compmemsize = (uLongf)( (rect->h * (rect->w + 1) * 3 * 1.001 + 1) + 12 ); if(!(compmem=(uint8 *)MDFN_malloc(compmemsize, _("PNG compression buffer")))) return 0; if(!(pp=fopen(fname, "wb"))) { return 0; } { static uint8 header[8]={137,80,78,71,13,10,26,10}; if(fwrite(header,8,1,pp)!=1) goto PNGerr; } { uint8 chunko[13]; chunko[0] = rect->w >> 24; // Width chunko[1] = rect->w >> 16; chunko[2] = rect->w >> 8; chunko[3] = rect->w; chunko[4] = rect->h >> 24; // Height chunko[5] = rect->h >> 16; chunko[6] = rect->h >> 8; chunko[7] = rect->h; chunko[8]=8; // 8 bits per sample(24 bits per pixel) chunko[9]=2; // Color type; RGB triplet chunko[10]=0; // compression: deflate chunko[11]=0; // Basic adapative filter set(though none are used). chunko[12]=0; // No interlace. if(!WritePNGChunk(pp,13,"IHDR",chunko)) goto PNGerr; } { uint8 *tmp_buffer; uint8 *tmp_inc; tmp_inc = tmp_buffer = (uint8 *)malloc((rect->w * 3 + 1) * rect->h); for(y=0;y<rect->h;y++) { *tmp_inc = 0; tmp_inc++; for(x=0;x<rect->w;x++) { int r,g,b; DECOMP_COLOR(*(uint32 *)((uint8 *)fb + (y + rect->y) * pitch + (x + rect->x) * 4), r, g, b); tmp_inc[0] = r; tmp_inc[1] = g; tmp_inc[2] = b; tmp_inc += 3; } } if(compress(compmem, &compmemsize, tmp_buffer, rect->h * (rect->w * 3 + 1))!=Z_OK) { if(tmp_buffer) free(tmp_buffer); goto PNGerr; } if(tmp_buffer) free(tmp_buffer); if(!WritePNGChunk(pp,compmemsize,"IDAT",compmem)) goto PNGerr; } if(!WritePNGChunk(pp,0,"IEND",0)) goto PNGerr; free(compmem); fclose(pp); return 1; PNGerr: if(compmem) free(compmem); if(pp) fclose(pp); return(0); }
int SaveSnapshot(void) { char *fn=0; int totallines=FSettings.LastSLine-FSettings.FirstSLine+1; int x,u,y; FILE *pp=NULL; uint8 *compmem=NULL; unsigned long compmemsize=totallines*263+12; if(!(compmem=FCEU_malloc(compmemsize))) return 0; for(u=0;u<999;u++) { pp=fopen((fn=FCEU_MakeFName(FCEUMKF_SNAP,u,"png")),"rb"); if(pp==NULL) break; fclose(pp); } if(!(pp=fopen(fn,"wb"))) return 0; { static uint8 header[8]={137,80,78,71,13,10,26,10}; if(fwrite(header,8,1,pp)!=1) goto PNGerr; } { uint8 chunko[13]; chunko[0]=chunko[1]=chunko[3]=0; chunko[2]=0x1; // Width of 256 chunko[4]=chunko[5]=chunko[6]=0; chunko[7]=totallines; // Height chunko[8]=8; // bit depth chunko[9]=3; // Color type; indexed 8-bit chunko[10]=0; // compression: deflate chunko[11]=0; // Basic adapative filter set(though none are used). chunko[12]=0; // No interlace. if(!WritePNGChunk(pp,13,"IHDR",chunko)) goto PNGerr; } { char pdata[256*3]; //void FCEUD_GetPalette(uint8 i,uint8 *r, unsigned char *g, unsigned char *b); for(x=0;x<256;x++) FCEUD_GetPalette(x,(uint8*)(pdata+x*3),(unsigned char*)(pdata+x*3+1),(unsigned char*)(pdata+x*3+2)); // static int WritePNGChunk(FILE *fp, uint32 size, char *type, uint8 *data) if(!WritePNGChunk(pp,256*3,"PLTE",(uint8 *)pdata)) goto PNGerr; } { uint8 *tmp=XBuf+FSettings.FirstSLine*272+8; uint8 *dest,*mal,*mork; /* If memory couldn't be allocated, just use XBuf(screen contents will be corrupted for one frame, though. */ if(!(mal=mork=dest=malloc((totallines<<8)+totallines))) mork=dest=XBuf; for(y=0;y<totallines;y++) { *dest=0; // No filter. dest++; for(x=256;x;x--,tmp++,dest++) *dest=*tmp; tmp+=16; } if(compress(compmem,&compmemsize,mork,(totallines<<8)+totallines)!=Z_OK) { if(mal) free(mal); goto PNGerr; } if(mal) free(mal); if(!WritePNGChunk(pp,compmemsize,"IDAT",compmem)) goto PNGerr; } if(!WritePNGChunk(pp,0,"IEND",0)) goto PNGerr; free(compmem); fclose(pp); #ifdef GP2X sync(); #endif return u+1; PNGerr: if(compmem) free(compmem); if(pp) fclose(pp); return(0); }
int NDS_WritePNG(const char *fname, u8 *data) { int x, y; int width=256; int height=192*2; u16 * bmp = (u16 *)data; FILE *pp=NULL; uint8 *compmem = NULL; uLongf compmemsize = (uLongf)( (height * (width + 1) * 3 * 1.001 + 1) + 12 ); if(!(compmem=(uint8 *)malloc(compmemsize))) return 0; if(!(pp=fopen(fname, "wb"))) { goto PNGerr; } { const uint8 header[8]={137,80,78,71,13,10,26,10}; if(fwrite(header,8,1,pp)!=1) goto PNGerr; } { uint8 chunko[13]; chunko[0] = width >> 24; // Width chunko[1] = width >> 16; chunko[2] = width >> 8; chunko[3] = width; chunko[4] = height >> 24; // Height chunko[5] = height >> 16; chunko[6] = height >> 8; chunko[7] = height; chunko[8]=8; // 8 bits per sample(24 bits per pixel) chunko[9]=2; // Color type; RGB triplet chunko[10]=0; // compression: deflate chunko[11]=0; // Basic adapative filter set(though none are used). chunko[12]=0; // No interlace. if(!WritePNGChunk(pp,13,"IHDR",chunko)) goto PNGerr; } { uint8 *tmp_buffer; uint8 *tmp_inc; tmp_inc = tmp_buffer = (uint8 *)malloc((width * 3 + 1) * height); for(y=0;y<height;y++) { *tmp_inc = 0; tmp_inc++; for(x=0;x<width;x++) { int r,g,b; u16 pixel = bmp[y*256+x]; r = pixel>>10; pixel-=r<<10; g = pixel>>5; pixel-=g<<5; b = pixel; r*=255/31; g*=255/31; b*=255/31; tmp_inc[0] = b; tmp_inc[1] = g; tmp_inc[2] = r; tmp_inc += 3; } } if(compress(compmem, &compmemsize, tmp_buffer, height * (width * 3 + 1))!=Z_OK) { if(tmp_buffer) free(tmp_buffer); goto PNGerr; } if(tmp_buffer) free(tmp_buffer); if(!WritePNGChunk(pp,compmemsize,"IDAT",compmem)) goto PNGerr; } if(!WritePNGChunk(pp,0,"IEND",0)) goto PNGerr; free(compmem); fclose(pp); return 1; PNGerr: if(compmem) free(compmem); if(pp) fclose(pp); return(0); }