#include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #define WB_DISKMAGIC 0xe310 #define WB_DISKVERSION 1 #define WB_DISKREVISION 1 #define WB_DISKREVISIONMASK 255 #define NO_ICON_POSITION (0x80000000) #define WBDISK 1 #define WBDRAWER 2 #define WBTOOL 3 #define WBPROJECT 4 #define WBGARBAGE 5 #define WBDEVICE 6 #define WBKICK 7 #define WBAPPICON 8 #define NONNULL 0x123456 struct { char *name; int minl, code; } icontype[] = { { "appicon", 1, WBAPPICON }, { "device", 2, WBDEVICE }, { "disk", 2, WBDISK }, { "drawer", 2, WBDRAWER }, { "garbage", 1, WBGARBAGE }, { "kick", 1, WBKICK }, { "project", 1, WBPROJECT }, { "tool", 1, WBTOOL }, }; #define NUM_ICONTYPES (sizeof(icontype)/sizeof(icontype[0])) typedef unsigned short pixval; typedef struct { pixval r, g, b; } pixel; void usage() { fprintf(stderr, "usage: ppmtoinfo [-type icontype][-floyd|-fs] [-map mapfile] [ppmfile] [ppmfile]\n"); exit(1); } void w16(FILE *file, int v) { putc((v>>8)&0xff, file); putc(v&0xff, file); } void w32(FILE *file, int v) { w16(file, v>>16); w16(file, v); } char *myalloc(int size) { char *p=malloc(size); if(!p) { fprintf(stderr, "out of memory!\n"); exit(1); } return p; } pixel **readppm(FILE *file, int *colsP, int *rowsP, pixval *maxvalP) { pixel** pixels; int row, col; int format, mv; if(4!=fscanf(file, "P%d %d %d %d", &format, colsP, rowsP, &mv) || (format!=3 && format!=6)) { fprintf(stderr, "bad magic number - not a ppm file\n"); exit(1); } if(format==6) getc(file); *maxvalP=mv; pixels = (pixel **)myalloc(*rowsP * sizeof(pixel*)); pixels[0] = (pixel *)myalloc(*rowsP * *colsP * sizeof(pixel)); for(row=1; row<*rowsP; row++) pixels[row] = &(pixels[0][row * *colsP]); for ( row = 0; row < *rowsP; ++row ) if(format==3) for( col = 0; col < *colsP; ++col) { int r, g, b; fscanf(file, "%d %d %d", &r, &g, &b); pixels[row][col].r=r; pixels[row][col].g=g; pixels[row][col].b=b; } else for( col = 0; col < *colsP; ++col) { pixels[row][col].r=getc(file); pixels[row][col].g=getc(file); pixels[row][col].b=getc(file); } return pixels; } char *makelibfilename(char *oldname) { char *newname; if(*oldname=='/') return oldname; newname=myalloc(strlen(oldname)+strlen(AMIWM_HOME)+2); sprintf(newname, AMIWM_HOME"/%s", oldname); return newname; } #define HSTYLE_COMPL 0 #define HSTYLE_BACKFILL 1 #define HSTYLE_IMAGE 2 void writeiconheader(FILE *file, int type, int hstyle, int cols, int rows, char *deftool, char **tooltypes, char *toolwin, int stksize) { int drw=0; if(type==1 || type==2 || type==5 || type==6) drw=1; w16(file, WB_DISKMAGIC); w16(file, WB_DISKVERSION); w32(file, 0); w16(file, 0); w16(file, 0); w16(file, cols); w16(file, rows); w16(file, 4|hstyle); w16(file, 3); w16(file, 1); w32(file, NONNULL); w32(file, (hstyle==HSTYLE_IMAGE? NONNULL:0)); w32(file, 0); w32(file, 0); w32(file, 0); w16(file, 0); w32(file, WB_DISKREVISION); putc(type, file); putc(0, file); w32(file, (deftool!=NULL? NONNULL:0)); w32(file, (tooltypes!=NULL? NONNULL:0)); w32(file, NO_ICON_POSITION); w32(file, NO_ICON_POSITION); w32(file, (drw? NONNULL:0)); w32(file, (toolwin? NONNULL:0)); w32(file, stksize); if(drw) { w16(file, 50); w16(file, 50); w16(file, 400); w16(file, 100); w16(file, ~0); w32(file, 0); w32(file, 0x0240027f); w32(file, 0); w32(file, 0); w32(file, NONNULL); w32(file, 0); w32(file, 0); w16(file, 90); w16(file, 40); w16(file, ~0); w16(file, ~0); w16(file, 1); w32(file, 0); w32(file, 0); } } void writeiconinit(FILE *file, int cols, int rows, int planes) { w16(file, 0); w16(file, 0); w16(file, cols); w16(file, rows); w16(file, planes); w32(file, NONNULL); putc((1<>l; putc(pat, file); } } void writeiconstr(FILE *file, char *str) { int l=strlen(str)+1; w32(file, l); fwrite(str, 1, l, file); } void writeiconend(FILE *file, int type, char *deftool, char **tooltypes, char *toolwin) { if(deftool) writeiconstr(file, deftool); if(tooltypes) { int n; for(n=0; tooltypes[n]!=NULL; n++); w32(file, 4*(n+1)); for(n=0; tooltypes[n]!=NULL; n++) writeiconstr(file, tooltypes[n]); } if(toolwin) writeiconstr(file, toolwin); if(type==1 || type==2 || type==5 || type==6) { w32(file, 0); w16(file, 0); } } #define mx(a,b) ((a)>(b)?(a):(b)) unsigned char *processicon(FILE *ifp, int floyd, pixel **mappixels, int maprows, int mapcols, pixval *mapmaxval, int *rowsP, int *colsP, int *planesP) { int rows, cols, planes, bpr, imgsz; pixval maxval; pixel **pixels, *colormap; unsigned char *outimg, *oip; register int row, col, limitcol; register pixel *pP; int newcolors; register int ind; long* thisrerr; long* nextrerr; long* thisgerr; long* nextgerr; long* thisberr; long* nextberr; long* temperr; register long sr, sg, sb, err; int fs_direction, dscale; pixels = readppm( ifp, &cols, &rows, &maxval ); if(ifp != stdin) fclose( ifp ); if ( *mapmaxval != maxval ) { if ( *mapmaxval > maxval ) fprintf(stderr, "rescaling colormap colors\n"); for ( row = 0; row < maprows; ++row ) for ( col = 0, pP = mappixels[row]; col < mapcols; ++col, ++pP ) { pP->r=((int)pP->r*maxval+*mapmaxval/2)/ *mapmaxval; pP->g=((int)pP->g*maxval+*mapmaxval/2)/ *mapmaxval; pP->b=((int)pP->b*maxval+*mapmaxval/2)/ *mapmaxval; } *mapmaxval = maxval; } newcolors=mapcols*maprows; colormap=mappixels[0]; if(newcolors>256) newcolors=256; for(planes=1; (1<>4); imgsz=rows*bpr*8*sizeof(unsigned char); outimg = (unsigned char *)myalloc(imgsz); memset(outimg, 0, imgsz); oip = outimg; dscale = 0; if(maxval>=16384) while(maxval>=(16384<r + thisrerr[col + 1] / 1024; sg = pP->g + thisgerr[col + 1] / 1024; sb = pP->b + thisberr[col + 1] / 1024; if ( sr < 0 ) sr = 0; else if ( sr > maxval ) sr = maxval; if ( sg < 0 ) sg = 0; else if ( sg > maxval ) sg = maxval; if ( sb < 0 ) sb = 0; else if ( sb > maxval ) sb = maxval; } else { sr = pP->r; sg = pP->g; sb = pP->b; } for ( i = 0; i < newcolors; ++i ) { r2 = sr - colormap[i].r; g2 = sg - colormap[i].g; b2 = sb - colormap[i].b; if (dscale) { r2 >>= dscale; g2 >>= dscale; b2 >>= dscale; } newdist = r2 * r2 + g2 * g2 + b2 * b2; if ( i==0 || newdist < dist ) { ind = i; dist = newdist; } } if ( floyd ) { /* Propagate Floyd-Steinberg error terms. */ if ( fs_direction ) { err = ( sr - (long) colormap[ind].r ) * 1024; thisrerr[col + 2] += ( err * 7 ) / 16; nextrerr[col ] += ( err * 3 ) / 16; nextrerr[col + 1] += ( err * 5 ) / 16; nextrerr[col + 2] += ( err ) / 16; err = ( sg - (long) colormap[ind].g ) * 1024; thisgerr[col + 2] += ( err * 7 ) / 16; nextgerr[col ] += ( err * 3 ) / 16; nextgerr[col + 1] += ( err * 5 ) / 16; nextgerr[col + 2] += ( err ) / 16; err = ( sb - (long) colormap[ind].b ) * 1024; thisberr[col + 2] += ( err * 7 ) / 16; nextberr[col ] += ( err * 3 ) / 16; nextberr[col + 1] += ( err * 5 ) / 16; nextberr[col + 2] += ( err ) / 16; } else { err = ( sr - (long) colormap[ind].r ) * 1024; thisrerr[col ] += ( err * 7 ) / 16; nextrerr[col + 2] += ( err * 3 ) / 16; nextrerr[col + 1] += ( err * 5 ) / 16; nextrerr[col ] += ( err ) / 16; err = ( sg - (long) colormap[ind].g ) * 1024; thisgerr[col ] += ( err * 7 ) / 16; nextgerr[col + 2] += ( err * 3 ) / 16; nextgerr[col + 1] += ( err * 5 ) / 16; nextgerr[col ] += ( err ) / 16; err = ( sb - (long) colormap[ind].b ) * 1024; thisberr[col ] += ( err * 7 ) / 16; nextberr[col + 2] += ( err * 3 ) / 16; nextberr[col + 1] += ( err * 5 ) / 16; nextberr[col ] += ( err ) / 16; } } oip[col] = ind; if ( ( ! floyd ) || fs_direction ) { ++col; ++pP; } else { --col; --pP; } } while ( col != limitcol ); oip += bpr*8; if ( floyd ) { temperr = thisrerr; thisrerr = nextrerr; nextrerr = temperr; temperr = thisgerr; thisgerr = nextgerr; nextgerr = temperr; temperr = thisberr; thisberr = nextberr; nextberr = temperr; fs_direction = ! fs_direction; } } if(floyd) { free(thisrerr); free(nextrerr); free(thisgerr); free(nextgerr); free(thisberr); free(nextberr); } free(pixels[0]); free(pixels); *rowsP=rows; *colsP=cols; *planesP=planes; return outimg; } int main(int argc, char *argv[]) { char *mapname = "system.map"; int argn, maprows, mapcols; int floyd; pixel **mappixels; pixval mapmaxval; FILE* ifp; FILE *ifp2=NULL; unsigned char *outimg; int planes, rows, cols; char *deftool=NULL, **tooltypes=NULL, *toolwin=NULL; int stksize=0; int type=WBPROJECT; argn = 1; floyd = 0; while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) { int l=strlen(argv[argn]); if ( !strncmp( argv[argn], "-fs", mx(l, 2) ) || !strncmp( argv[argn], "-floyd", mx(l, 2) ) ) floyd = 1; else if ( !strncmp( argv[argn], "-nofs", mx(l, 2) ) || !strncmp( argv[argn], "-nofloyd", mx(l, 2) ) ) floyd = 0; else if ( !strncmp( argv[argn], "-map", mx(l, 2) ) ) { ++argn; if ( argn == argc ) usage(); mapname = argv[argn]; } else if ( !strncmp( argv[argn], "-type", mx(l, 2) ) ) { int i; ++argn; if ( argn == argc ) usage(); l=strlen(argv[argn]); for(i=0; i=NUM_ICONTYPES) { fprintf(stderr, "Unknown icon type. Supported types:\n"); for(i=0; i>4), rows, planes); free(outimg); if(ifp2) { outimg = processicon(ifp2, floyd, mappixels, maprows, mapcols, &mapmaxval, &rows, &cols, &planes); writeiconinit(stdout, cols, rows, planes); writeiconimage(stdout, outimg, 16*((cols+15)>>4), rows, planes); free(outimg); } writeiconend(stdout, type, deftool, tooltypes, toolwin); return 0; }