/* * xvalg.c - image manipulation algorithms (Blur, etc.) * * Author: John Bradley, University of Pennsylvania * (bradley@cis.upenn.edu) * * Contains: * void AlgInit(); * void DoAlg(int algnum); * static void NoAlg(); * static void Blur(int size); * static void EdgeDetect(int tinfoil); */ /* Copyright Notice * ================ * Copyright 1989, 1990, 1991, 1992, 1993 by John Bradley * * Permission to use, copy, and distribute XV in its entirety, for * non-commercial purposes, is hereby granted without fee, provided that * this license information and copyright notice appear in all copies. * * Note that distributing XV 'bundled' in with ANY product is considered * to be a 'commercial purpose'. * * Also note that any copies of XV that are distributed MUST be built * and/or configured to be in their 'unregistered copy' mode, so that it * is made obvious to the user that XV is shareware, and that they should * consider donating, or at least reading this License Info. * * The software may be modified for your own purposes, but modified * versions may NOT be distributed without prior consent of the author. * * This software is provided 'as-is', without any express or implied * warranty. In no event will the author be held liable for any damages * arising from the use of this software. * * If you would like to do something with XV that this copyright * prohibits (such as distributing it with a commercial product, * using portions of the source in some other program, etc.), please * contact the author (preferably via email). Arrangements can * probably be worked out. * * XV is shareware for PERSONAL USE only. You may use XV for your own * amusement, and if you find it nifty, useful, generally cool, or of * some value to you, your non-deductable donation would be greatly * appreciated. $25 is the suggested donation, though, of course, * larger donations are quite welcome. Folks who donate $25 or more * can receive a Real Nice bound copy of the XV manual for no extra * charge. * * Commercial, government, and institutional users MUST register their * copies of XV, for the exceedingly REASONABLE price of just $25 per * workstation/X terminal. Site licenses are available for those who * wish to run XV on a large number of machines. Contact the author * for more details. * * The author may be contacted via: * US Mail: John Bradley * 1053 Floyd Terrace * Bryn Mawr, PA 19010 * * Phone: (215) 898-8813 * EMail: bradley@cis.upenn.edu */ #include "xv.h" #ifdef __STDC__ static void NoAlg(void); static void Blur(int); static void EdgeDetect(int); static void OilPaint(void); static void saveOrigPic(void); static void doConvolv(byte *, int,int, int *,int,int,int, byte *, int,int); static void doBlurConvolv(byte *, int, int, byte *, int); static void doEdgeConvolv(byte *, int, int, byte *, int); static void doOilPaint(byte *, int, int, byte *, int); static int start24bitAlg(byte **, byte **); static void end24bitAlg(byte *, byte *); #else static void NoAlg(), Blur(), EdgeDetect(), OilPaint(), saveOrigPic(); static void doConvolv(), doBlurConvolv(), doEdgeConvolv(), doOilPaint(); static int start24bitAlg(); static void end24bitAlg(); #endif static byte *origPic = (byte *) NULL; static int origPicType; static byte origrmap[256], origgmap[256], origbmap[256]; #undef TIMING_TEST #ifdef TIMING_TEST #include #endif /***************************/ static void printUTime(str) char *str; { #ifdef TIMING_TEST int i; struct rusage ru; i = getrusage(RUSAGE_SELF, &ru); fprintf(stderr,"%s: utime = %ld.%ld seconds\n", str, ru.ru_utime.tv_sec, ru.ru_utime.tv_usec); #endif } /************************************************************/ void AlgInit() { /* called whenver an image file is loaded. disposes of origPic if neccessary, and points it to null */ if (origPic) free(origPic); origPic = (byte *) NULL; algMB.dim[ALG_NONE] = 1; /* can't undo when init'ed already */ } /************************/ void DoAlg(anum) int anum; { /* called with a value from the algMB button. Executes the specified algorithm */ switch (anum) { case ALG_NONE: NoAlg(); break; case ALG_BLUR3: Blur(3); break; case ALG_BLUR5: Blur(5); break; case ALG_BLUR7: Blur(7); break; case ALG_EDGE: EdgeDetect(0); break; case ALG_TINF: EdgeDetect(1); break; case ALG_OIL: OilPaint(); break; } algMB.dim[ALG_NONE] = (anum == ALG_NONE); } /************************/ static void NoAlg() { int i; /* restore original picture */ if (!origPic) return; /* none to restore */ WaitCursor(); KillOldPics(); /* toss the old pic/cpic/epic/theImage away */ picType = origPicType; Set824Menus(picType); pic = origPic; origPic = NULL; if (picType == PIC8) { for (i=0; i<256; i++) { rMap[i] = origrmap[i]; gMap[i] = origgmap[i]; bMap[i] = origbmap[i]; } } InstallNewPic(); } /************************/ static void Blur(n) int n; { /* runs a n*n convolution mask (all 1's) over 'pic', producing a 24-bit version. Then calls 24to8 to generate a new 8-bit image, and installs it. Note that 'n' must be odd for things to work properly */ byte *pic24, *tmpPic; int *blurMatrix, i; WaitCursor(); SetISTR(ISTR_INFO, "Blurring with %dx%d convolution mask...",n,n); if (start24bitAlg(&pic24, &tmpPic)) return; doBlurConvolv(pic24, pWIDE,pHIGH, tmpPic, n); end24bitAlg(pic24, tmpPic); } /************************/ static void EdgeDetect(tinfoil) int tinfoil; { byte *pic24, *p24, *tmpPic; char *str; int i, v, maxv; WaitCursor(); if (tinfoil) str = "Doing cheesy embossing effect..."; else str = "Doing edge detection..."; SetISTR(ISTR_INFO, str); if (start24bitAlg(&pic24, &tmpPic)) return; if (tinfoil) { /* fill tmpPic with gray128 */ int i; byte *tp; for (i=0, tp=tmpPic; imaxv) maxv = v; } for (i=0, p24=tmpPic; i=0 && y1=0 && x1=0 && y1=0 && x1=0 && i=0 && j>2]; if (k > rcnt) { rval = *pp; rcnt = k; } pp++; k = ++ghist[*pp>>2]; if (k > gcnt) { gval = *pp; gcnt = k; } pp++; k = ++bhist[*pp>>2]; if (k > bcnt) { bval = *pp; bcnt = k; } pp++; } else pp += 3; } } plin += bperlin; pp = plin; } *rp++ = (byte) rval; *rp++ = (byte) gval; *rp++ = (byte) bval; p24 += 3; } } printUTime("end of doOilPaint"); } /***********************************************/ static int start24bitAlg(pic24, tmpPic) byte **pic24, **tmpPic; { /* generates a 24-bit version of 'pic', if neccessary, and also mallocs * a pWIDE*pHIGH*3 24-bit output pic. * * Returns '1' if there's some sort of screwup, '0' if cool */ if (picType == PIC8) { *pic24 = Conv8to24(pic, pWIDE, pHIGH, rMap, gMap, bMap); if (!*pic24) { SetCursors(-1); return 1; } } else *pic24 = pic; /* need to create another w*h*3 pic to hold results */ *tmpPic = (byte *) calloc(pWIDE * pHIGH * 3, 1); if (!(*tmpPic)) { SetCursors(-1); ErrPopUp("Unable to malloc() tmp 24-bit image in start24bitAlg()", "\nTough!"); if (picType == PIC8) free(*pic24); return 1; } return 0; } /***********************************************/ static void end24bitAlg(pic24, outPic) byte *pic24, *outPic; { /* given pic24, and outPic, which has the new 24-bit image, installs it */ saveOrigPic(); /* also kills pic/cpic/epic/egampic/theImage, NOT pic24 */ xvbcopy(outPic, pic24, pWIDE*pHIGH*3); /* copy results into pic24 */ free(outPic); if (picType == PIC8) { pic = Conv24to8(pic24, pWIDE, pHIGH, ncols, rMap,gMap,bMap); free(pic24); if (!pic) { SetCursors(-1); ErrPopUp("Some sort of failure occured in 24to8 conversion\n", "Damn!"); NoAlg(); return; } } else pic = pic24; InstallNewPic(); } /************************/ static void saveOrigPic() { /* saves original picture into origPic, if it hasn't already been done. This allows us to undo algorithms... Also, frees all pics, (except 'pic', if we're in PIC24 mode) */ int i; FreeEpic(); if (cpic && cpic != pic) free(cpic); xvDestroyImage(theImage); theImage = NULL; cpic = NULL; if (!origPic) { /* make a backup copy of 'pic' */ origPic = (byte *) malloc(pWIDE * pHIGH * ((picType==PIC8) ? 1 : 3)); if (!origPic) FatalError("out of memory in 'saveOrigPic()'"); xvbcopy(pic, origPic, pWIDE * pHIGH * ((picType==PIC8) ? 1 : 3)); origPicType = picType; if (picType == PIC8) { for (i=0; i<256; i++) { /* save old colormap */ origrmap[i] = rorg[i]; origgmap[i] = gorg[i]; origbmap[i] = borg[i]; } } } if (picType != PIC24) { /* kill pic, as well */ if (pic) free(pic); pic = NULL; } }