/* -*- C -*- * OPTICON.C * * (c)Copyright 1994 by Tobias Ferber, ukjg@rz.uni-karlsruhe.de * * This file is part of the IconTools distribution * * OptIcon is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 1 of the License, * or (at your option) any later version. * * OptIcon is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* $VER: $Id: opticon.c,v 1.16 1995/08/06 20:39:35 tf Exp $ */ #include "version.h" static char versiontag[] = "$VER: $Id: opticon.c,v 1.16 1995/08/06 20:39:35 tf Exp $"; /* Compile w/ -DDEBUG to output more information at runtime */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "memfn.h" #ifdef __GNUC__ /* suggest parentheses around assignment used as truth value */ #define if(assignment) if( (assignment) ) #endif /* __GNUC__ */ extern struct Library *OpenLibrary(STRPTR, ULONG); extern void CloseLibrary(struct Library *); extern void CopyMem(APTR, APTR, ULONG); extern void *AllocMem(ULONG, ULONG); extern void FreeMem(void *, ULONG); extern ULONG TypeOfMem(void *); extern struct RDArgs *ReadArgs(STRPTR, LONG *, struct RDArgs *); extern LONG IoErr(void); extern BOOL PrintFault(LONG, STRPTR); extern BPTR Lock(STRPTR, LONG); extern void UnLock(BPTR); extern void FreeArgs(struct RDArgs *); extern struct DiskObject *GetDiskObject(char *); extern BOOL PutDiskObject(char *, struct DiskObject *); extern void FreeDiskObject(struct DiskObject *); struct IconBase *IconBase; void display_version_information(void) { static char license[]= "OptIcon is free software; you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published\n" "by the Free Software Foundation; either version 1 of the License,\n" "or (at your option) any later version.\n" "\n" "OptIcon is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n" "\n" "You should have received a copy of the GNU General Public License\n" "along with OptIcon; see the file COPYING. If not, write to the\n" "Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n" ; puts("\nOptIcon Version " VERSION " (compiled " __DATE__ ", " __TIME__ ")\n" "(c)Copyright 1994,95 by Tobias Ferber, ukjg@rz.uni-karlsruhe.de\n"); puts(license); } struct Image *free_image(struct Image *i) { if(i) { long size= i->Depth * i->Height * ((i->Width + 15) / 16) * sizeof(UWORD); if(i->ImageData && size > 0) FreeMem( i->ImageData, size ); FreeMem( i, sizeof(struct Image) ); } return (struct Image *)0L; } /* command line options */ #define OPT_NOEXPAND (1<<0) #define OPT_CRITICAL (1<<1) #define OPT_VERBOSE (1<<2) #define OPT_REMAPV37 (1<<3) struct Image *optimize_image(struct Image *i, WORD planes, int optimode) { UWORD p16= i->Height * ((i->Width + 15) / 16); /* #of words per plane */ UWORD *idata= i->ImageData; WORD d, dmax, D, P; UBYTE pp= 0; /* plane pick */ UBYTE p10= 0; /* plane on/off */ struct Image *o= i; /* optimized image */ /* prevent silly args from being harmful */ if(!i) return i; if(planes > 8) planes= 8; if(optimode & OPT_VERBOSE) { printf("(depth=%d, pick=%d, onoff=%d)", i->Depth, i->PlanePick, i->PlaneOnOff); fflush(stdout); } /* PRESCAN: Examine dmax planes of i and compute D = the real depth (without trailing 0 planes) pp = the new PlanePick value p10 = the new PlaneOnOff value */ dmax= (0 < planes && planes < i->Depth) ? planes : i->Depth; for(d= D= 0; dPlanePick & (1<PlaneOnOff & (1<PlanePick || p10 != i->PlaneOnOff) ) { printf(" -> (%d,%d,%d)", D,pp,p10); fflush(stdout); } /* compute the #of planes in the output image */ P= ( planes>D && !(optimode & OPT_NOEXPAND) ) ? planes : D; if(P != i->Depth || pp != i->PlanePick || p10 != i->PlaneOnOff) { UWORD p8= p16 * sizeof(UWORD); UWORD *odata; ULONG osize= P * p8; if( o= (struct Image *)AllocMem(sizeof(struct Image),MEMF_CLEAR) ) { if( odata= (UWORD *)AllocMem(osize,TypeOfMem(i->ImageData)|MEMF_CLEAR) ) { CopyMem( (APTR)i, (APTR)o, sizeof(struct Image) ); o->ImageData= odata; idata= i->ImageData; for(d=0; dPlanePick & (1<PlaneOnOff & (1<PlanePick & (1<=3 && D 2, (2) invert the result, (3) AND it with plane 2 and (4) OR the result with all planes > 2 Note: There is no need to expand the image data if p10 &~ %111 != 0 */ /* move to plane 2 */ idata= i->ImageData; for(d=0; d<2; d++) if(i->PlanePick & (1<PlanePick & (1<<2)) { memcpy((char *)p, (char *)idata, p8); idata= &idata[p16]; } else memset( (char *)p, (p10 & (1L<<2)) ? 0xFF : 0x00, p8 ); /* or planes 3..D, invert them, AND the result with plane 2 */ for(d=3; dPlanePick & (1<PlaneOnOff is 0 --> no-op */ } /* move to plane 3 */ odata= o->ImageData; for(d=0; d<3; d++) if(pp & (1<=D || pp & (1<ImageData; if( p10 &~ (1<<(D-1)) == 0) { memset( (char *)p, 0x00, p8 ); for(d=0; dPlanePick & (1<PlanePick & (1<<(D-1)) ) memand( (char *)p, (char *)idata, p8 ); /* else the last plane is entirely 1 */ } else /* move to the last plane */ { for(d=0; dPlanePick & (1<PlanePick & (1<<(D-1)) ) memcpy( (char *)p, (char *)idata, p8 ); else memset( (char *)p, 0xFF, p8 ); } /* move to plane D */ odata= o->ImageData; for(d=0; d panic! */ { FreeMem(o->ImageData,osize); FreeMem(o,sizeof(struct Image)); o= (struct Image *)0L; } } o->Depth= P; o->PlanePick= pp; o->PlaneOnOff= p10; } else /* !odata */ { FreeMem(o,sizeof(struct Image)); o= (struct Image *)0L; } } } if(optimode & OPT_VERBOSE) { if(o && o!=i) printf(" -> (%d,%d,%d)", o->Depth, o->PlanePick, o->PlaneOnOff); putchar('\n'); } return o; } /**/ static char *tackon(char *pname, char *fname) { char *buf= (char *)malloc(strlen(pname)+strlen(fname)+2); if(buf) { register char *s= buf; *s= '\0'; if(pname) { register int n= 0; while( *pname ) n++, *s++= *pname++; if( n>0 && buf[n-1]!=':' && buf[n-1]!='/' ) *s++ = '/'; } if(fname) while( *fname ) *s++ = *fname++; *s= '\0'; } return buf; } /* main, opticon(), and doall() share the following vars */ static char *whoami; static LONG args[8] = { 0,0,0,0,0,0,0,0 }; WORD numplanes= 0; int optiflags= 0; int opticon(char *fname) { int rc= RETURN_OK; /* We initially assume `fname' to be or to have an icon. */ char *iname= (char *)strdup(fname); if(optiflags & OPT_VERBOSE) printf("opticon `%s'\n",fname); if(iname) { struct DiskObject *icon; if( (icon= GetDiskObject(iname)) == NULL ) { size_t x= strlen(iname) - 5; if(x>0 && !stricmp(&(iname[x]),".info")) { iname[x]= '\0'; icon= GetDiskObject(iname); } } if(icon) { struct Gadget *g= &icon->do_Gadget; struct Image *ogr, *osr; int modified= 0; ogr= osr= (struct Image *)0L; if(g->GadgetRender && (g->Flags & GFLG_GADGIMAGE)) { struct Image *i= (struct Image *)g->GadgetRender; if(optiflags & OPT_VERBOSE) printf(" :normal "), fflush(stdout); if( ogr= optimize_image(i,numplanes,optiflags) ) { if(ogr != i) { g->GadgetRender= (APTR)ogr; ++modified; } else ogr= (struct Image *)0L; /* don't free ogr */ if(g->SelectRender && (g->Flags & GFLG_GADGHIMAGE)) { i= (struct Image *)g->SelectRender; if(optiflags & OPT_VERBOSE) printf(" :selected "), fflush(stdout); if( osr= optimize_image(i,numplanes, optiflags) ) { if(osr != i) { g->SelectRender= (APTR)osr; ++modified; } else osr= (struct Image *)0L; /* don't free osr */ } else { fprintf(stderr,"%s: %s.info: not enough free memory to optimize the selected image\n",whoami,iname); rc= ERROR_NO_FREE_STORE; } } } else { fprintf(stderr,"%s: %s.info: not enough free memory to optimize the normal image\n",whoami,iname); rc= ERROR_NO_FREE_STORE; } } /* SMART/S */ if( rc == RETURN_OK && args[6] && (icon->do_Type == WBDRAWER || icon->do_Type == WBGARBAGE) ) { BPTR lock= Lock(iname,ACCESS_READ); if( BADDR(lock) ) UnLock(lock); else { icon->do_Type = WBTOOL; ++modified; } } if( modified && rc == RETURN_OK ) { if( !PutDiskObject(iname,icon) ) PrintFault(rc= IoErr(), iname); } if(ogr) ogr= free_image(ogr); if(osr) osr= free_image(osr); FreeDiskObject(icon); } else /* !icon */ { PrintFault(rc= IoErr(), iname); fprintf(stderr,"%s: GetDiskObject() failed for %s[.info]\n",whoami,iname); if(args[7]) rc= RETURN_OK; /* keep running */ } free(iname); } else /* !iname */ { fprintf(stderr,"%s: out of memory... aaaiiiiiieeeeeeeee!\n",whoami); rc= ERROR_NO_FREE_STORE; } return rc; } int doall(char *pname) { int rc= RETURN_OK; struct FileInfoBlock *fib= (struct FileInfoBlock *)AllocDosObject(DOS_FIB, NULL); if(optiflags & OPT_VERBOSE) printf("scanning `%s'\n",pname); if(fib) { /* set to 1 if we are to call opticon(pname) after UnLock() */ int optme= 0; BPTR lock= Lock(pname, ACCESS_READ); if( BADDR(lock) ) { if( Examine(lock,fib) ) { /* not the initial call from main() for a file with ALL */ if( (optme= (fib->fib_DirEntryType > 0) ? 0:1) == 0 ) { while( (rc==RETURN_OK) && ExNext(lock,fib) && (IoErr() != ERROR_NO_MORE_ENTRIES) ) { char *pcat= tackon(pname,fib->fib_FileName); if(pcat) { if(optiflags & OPT_VERBOSE) printf("found `%s'\n",pcat); if( fib->fib_DirEntryType > 0 ) /* directory */ { rc= doall(pcat); } else /* file */ { size_t x= strlen(pcat) - 5; if( stricmp(&pcat[x],".info") == 0 ) /* "*.info" file */ { rc= opticon(pcat); } } free(pcat); } else /* !pcat */ { fprintf(stderr,"%s: out of memory... aaaiiiiiieeeeeeeee!\n",whoami); rc= ERROR_NO_FREE_STORE; } } } } else PrintFault(rc= IoErr(), pname); /* Examine() failed */ UnLock(lock); } else optme= 1; /* !lock */ /*else PrintFault(rc= IoErr(), pname);*/ if(optme && rc==RETURN_OK) rc= opticon(pname); FreeDosObject(DOS_FIB,fib); } else /* !fib */ { fprintf(stderr,"%s: out of memory... aaaiiiiiieeeeeeeee!\n",whoami); rc= ERROR_NO_FREE_STORE; } return rc; } /**/ int main(int argc, char **argv) { struct RDArgs *a; int rc= RETURN_OK; whoami= *argv; if( a= ReadArgs("FROM=NAME/A/M," /* 0 */ "DEPTH=PLANES/N," /* 1 */ "NOEXPAND/S," /* 2 */ "CRITICAL/S," /* 3 */ "REMAPV37/S," /* 4 */ "VERBOSE/S," /* 5 */ "SMART/S," /* 6 */ "ALL/S", /* 7 */ args, NULL) ) { char **flist= (char **)args[0]; if(args[1]) { if( (numplanes= (WORD)*(LONG *)(args[1])) < 1 ) { fprintf(stderr,"%s: Illegal maximum depth %d\n",whoami,numplanes); rc= RETURN_FAIL; } } if(flist && rc == RETURN_OK) { if( IconBase= (struct IconBase *)OpenLibrary(ICONNAME,36) ) { if(args[2]) optiflags |= OPT_NOEXPAND; if(args[3]) optiflags |= OPT_CRITICAL; if(args[4]) optiflags |= OPT_REMAPV37; if(args[5]) optiflags |= OPT_VERBOSE; for(;*flist && rc == RETURN_OK;flist++) rc= args[7] ? doall(*flist) : opticon(*flist); CloseLibrary((struct Library *)IconBase); } else { fprintf(stderr,"%s: You need %s V36+",whoami,ICONNAME); rc= RETURN_ERROR; } } FreeArgs(a); } else /* !ReadArgs */ { if(argc == 1) display_version_information(); else PrintFault(rc= IoErr(),NULL); } return rc; }