home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / enhance / enhance.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  17.7 KB  |  807 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    enhance - 
  19.  *        Enhance an image interactively 
  20.  *
  21.  *            Paul Haeberli - 1991
  22.  *
  23.  */
  24. #include "math.h"
  25. #include "stdio.h"
  26. #include "gl.h"
  27. #include "device.h"
  28. #include "image.h"
  29. #include "canvas.h"
  30. #include "vect.h"
  31. #include "showcaseui.h"
  32.  
  33. float flerp();
  34. canvas *applyprocess();
  35.  
  36. #define    CBALSCALE     (1.0)
  37. #define    DUOTONESCALE     (1.0)
  38.  
  39. #define    BLACKCOLOR     (0x000000)
  40. #define    BACKCOLOR     (0xd0d0d0)
  41. #define    REDCOLOR     (0x0000c0)
  42.  
  43. #define    DRAW_BACK    (1)
  44. #define    DRAW_IMAGES    (2)
  45. #define    DRAW_CONTROLS    (4)
  46. #define    PROC_IMAGES    (8)
  47.  
  48. #define STDSIZE        (200)
  49. #define STDSPACE    (10)
  50. #define STDSKIP        (STDSIZE+STDSPACE)
  51.  
  52. #define CONX         (STDSPACE+3*STDSKIP)
  53. #define CONWIDTH    (250)
  54. #define RADIOY        (183)
  55. #define RADIODY        (26)
  56. #define BUTTONDY    (32)
  57.  
  58. #define WINYSIZE    (3*STDSIZE+4*STDSPACE)
  59. #define WINXSIZE    (WINYSIZE+CONWIDTH)
  60.  
  61. #define MODE_GAMMA    (0)
  62. #define MODE_COLOR    (1)
  63. #define MODE_SHADOW    (2)
  64. #define MODE_HIGHLIGHT     (3)
  65. #define MODE_SATURATE    (4)
  66. #define MODE_DUOTONE     (5)
  67. #define MODE_ADDNOISE     (6)
  68. #define MODE_QUANTIZE     (7)
  69. #define MODE_SHARPEN     (8)
  70.  
  71. #define MAXSTEPS    500
  72.  
  73. long xorg, yorg;
  74. int wxsize, wysize;
  75. int curmode, nops;
  76. int func[MAXSTEPS];
  77. float args[MAXSTEPS][3];
  78. canmap *map;
  79. char *origname, *procname;
  80. canvas *inimage, *new, *origimage;
  81. Button *butquit, *butgamma, *butcolor, *butshadow, 
  82.         *butbrightness, *butsaturate, *butduotone,
  83.         *butaddnoise, *butquantize, *butsharpen,
  84.         *butwrite, *butshoworig, *butrestart;
  85.  
  86. int transfunc(in,out)
  87. vect *in, *out;
  88. {
  89.     float cr, cg, cb;
  90.     float sr, sg, sb;
  91.  
  92.     corone4(in->x,in->y,in->z,&cr,&cg,&cb);
  93.     sproof4(cr,cg,cb,&sr,&sg,&sb);
  94.     out->x = sr;
  95.     out->y = sg;
  96.     out->z = sb;
  97. }
  98.  
  99. canvas *readimage(iname)
  100. char *iname;
  101. {
  102.     int xsize, ysize, max;
  103.     float zfactor;
  104.     char cmd[256];
  105.     char tempname[256];
  106.     canvas *c;
  107.  
  108.     strcpy(tempname,"/usr/tmp/ENXXXXXX");
  109.     mktemp(tempname);
  110.     sizeofimage(iname,&xsize,&ysize);
  111.     if(xsize>ysize)
  112.     max = xsize;
  113.     else
  114.     max = ysize;
  115.     if(max<(STDSIZE-4) || max>(STDSIZE+4)) {
  116.     zfactor = STDSIZE/(float)max;
  117.     sprintf(cmd,"izoom %s %s %f %f -b",iname,tempname,zfactor,zfactor);
  118.     system(cmd);
  119.     c = imagetocanvas(tempname);
  120.     sprintf(cmd,"rm %s",tempname);
  121.     system(cmd);
  122.     return c;
  123.     }
  124.     return imagetocanvas(iname);
  125. }
  126.  
  127. restart()
  128. {
  129.     nops = 0;
  130.     freecanvas(inimage);
  131.     inimage = clonecanvas(origimage);
  132.     activatebut(butgamma);
  133.     curmode = MODE_GAMMA;
  134.     drawscene(DRAW_IMAGES|DRAW_CONTROLS|PROC_IMAGES);
  135. }
  136.  
  137. blat()
  138. {
  139.     manifesto();
  140. }
  141.  
  142.  
  143. main(int argc, char **argv)
  144. {
  145.     long        dev, mx, my;
  146.     short       val, smx, smy;
  147.  
  148.     if( argc<3 ) {
  149.     fprintf(stderr,"usage: enhance inimage.rgb outimage.rgb\n");
  150.     exit(1);
  151.     } 
  152.     origname = argv[1];
  153.     procname = argv[2];
  154.     initialize();
  155.     activate();
  156.     percentdone(50.0);
  157.     drawscene(DRAW_BACK+DRAW_CONTROLS);
  158.     drawboldlabel("Zooming source image down for display . . .",100,WINYSIZE/2);
  159.     inimage = readimage(origname);
  160.     cpack(BACKCOLOR);
  161.     rectfi(0,0,CONX-4,WINYSIZE);
  162.     drawscene(DRAW_IMAGES|PROC_IMAGES);
  163.     origimage = clonecanvas(inimage);
  164.     while (1) {
  165.     switch (dev = qread(&val)) {
  166.         case LEFTMOUSE:
  167.         qread(&smx); qread(&smy);
  168.         mx = smx - xorg;
  169.         my = smy - yorg;
  170.         if (val == UIBUTTONDOWN) {
  171.             sginap(8);
  172.             if (qtest() == dev) {
  173.             short tmp;
  174.             qread(&tmp); qread(&tmp); qread(&tmp);
  175.             val = UIBUTTONCLICK;
  176.             }
  177.         }
  178.         handleevents(mx, my, dev, (long) val);
  179.         if(val != 1)
  180.             locatemouseevents(mx,my);
  181.         break;
  182.         case MOUSEX:
  183.         mx = val - xorg;
  184.         break;
  185.         case MOUSEY:
  186.         my = val - yorg;
  187.         if(!getbutton(LEFTMOUSE))
  188.             locatemouseevents(mx,my);
  189.         break;
  190.         case REDRAW:
  191.         getorigin(&xorg,&yorg);
  192.         drawscene(DRAW_BACK+DRAW_CONTROLS+DRAW_IMAGES);
  193.         break;
  194.     }
  195.     }
  196. }
  197.  
  198. initialize()
  199. {
  200.     wysize = 3*STDSIZE+4*STDSPACE;
  201.     wxsize = wysize+CONWIDTH;
  202.     autoprefsize(wxsize,wysize);
  203.     winopen("Image Enhance");
  204.     RGBmode();
  205.     gconfig();
  206.     drawback();
  207.  
  208.     butquit = newpushbut(wxsize-10-75,10);
  209.     butgamma =      newradiobut(CONX+40,RADIOY+8*RADIODY);
  210.     butcolor =      newradiobut(CONX+40,RADIOY+7*RADIODY);
  211.     butshadow =     newradiobut(CONX+40,RADIOY+6*RADIODY);
  212.     butbrightness = newradiobut(CONX+40,RADIOY+5*RADIODY);
  213.     butsaturate =   newradiobut(CONX+40,RADIOY+4*RADIODY);
  214.     butduotone =    newradiobut(CONX+40,RADIOY+3*RADIODY);
  215.     butaddnoise =   newradiobut(CONX+40,RADIOY+2*RADIODY);
  216.     butquantize =   newradiobut(CONX+40,RADIOY+1*RADIODY);
  217.     butsharpen =    newradiobut(CONX+40,RADIOY+0*RADIODY);
  218.  
  219.     butwrite = newpushbut(CONX+40,20+RADIOY-3*BUTTONDY);
  220.     butshoworig = newpushbut(CONX+40,20+RADIOY-4*BUTTONDY);
  221.     butrestart = newpushbut(CONX+40,20+RADIOY-5*BUTTONDY);
  222.  
  223.     getorigin(&xorg,&yorg);
  224. }
  225.  
  226. activate()
  227. {
  228.     initbut();
  229.  
  230.     qdevice(LEFTMOUSE);
  231.     qdevice(MOUSEX);
  232.     qdevice(MOUSEY);
  233.     tie(LEFTMOUSE, MOUSEX, MOUSEY);
  234.  
  235.     loadbut(butquit,"Quit");
  236.     loadbut(butgamma,"Gamma");
  237.     loadbut(butcolor,"Color Balance");
  238.     linkbuttons(butgamma,butcolor);
  239.     loadbut(butshadow,"Shadow Detail");
  240.     linkbuttons(butgamma,butshadow);
  241.     loadbut(butbrightness,"Brightness");
  242.     linkbuttons(butgamma,butbrightness);
  243.     loadbut(butsaturate,"Saturation");
  244.     linkbuttons(butgamma,butsaturate);
  245.     loadbut(butduotone,"Duotone");
  246.     linkbuttons(butgamma,butduotone);
  247.     loadbut(butaddnoise,"Add Noise");
  248.     linkbuttons(butgamma,butaddnoise);
  249.     loadbut(butquantize,"Quantize");
  250.     linkbuttons(butgamma,butquantize);
  251.     loadbut(butsharpen,"Sharpen");
  252.     linkbuttons(butgamma,butsharpen);
  253.  
  254.     activatebut(butgamma);
  255.  
  256.     loadbut(butwrite,"Write Output");
  257.     loadbut(butshoworig,"Show Original");
  258.     loadbut(butrestart,"Start Over");
  259. }
  260.  
  261. newmode(mode)
  262. int mode;
  263. {
  264.     if(curmode != mode) {
  265.     curmode = mode;
  266.     drawscene(DRAW_IMAGES|PROC_IMAGES);
  267.     }
  268. }
  269.  
  270. handleevents(long mx, long my, long dev, long val)
  271. {
  272.     char cmd[256];
  273.  
  274.     if (selectedpressbut(butquit,mx,my,val)) {
  275.     exit(0);
  276.     } else if(inimages(mx,my,val)) {
  277.     return;
  278.     } else if (selectedpressbut(butgamma,mx,my,val)) {
  279.     newmode(MODE_GAMMA);
  280.     } else if (selectedpressbut(butcolor,mx,my,val)) {
  281.     newmode(MODE_COLOR);
  282.     } else if (selectedpressbut(butshadow,mx,my,val)) {
  283.     newmode(MODE_SHADOW);
  284.     } else if (selectedpressbut(butbrightness,mx,my,val)) {
  285.     newmode(MODE_HIGHLIGHT);
  286.     } else if (selectedpressbut(butsaturate,mx,my,val)) {
  287.     newmode(MODE_SATURATE);
  288.     } else if (selectedpressbut(butduotone,mx,my,val)) {
  289.     newmode(MODE_DUOTONE);
  290.     } else if (selectedpressbut(butaddnoise,mx,my,val)) {
  291.     newmode(MODE_ADDNOISE);
  292.     } else if (selectedpressbut(butquantize,mx,my,val)) {
  293.     newmode(MODE_QUANTIZE);
  294.     } else if (selectedpressbut(butsharpen,mx,my,val)) {
  295.     newmode(MODE_SHARPEN);
  296.     } else if (selectedpressbut(butduotone,mx,my,val)) {
  297.     newmode(MODE_DUOTONE);
  298.     } else if (selectedpressbut(butwrite,mx,my,val)) {
  299.     applytoimage(origname,procname);
  300.     percentdone(50.0);
  301.     sprintf(cmd,"ipaste %s",procname);
  302.     system(cmd);
  303.     percentdone(100.0);
  304.     } else if (selectedpressbut(butshoworig,mx,my,val)) {
  305.     percentdone(50.0);
  306.     sprintf(cmd,"ipaste %s",origname);
  307.     system(cmd);
  308.     percentdone(100.0);
  309.     } else if (selectedpressbut(butrestart,mx,my,val)) {
  310.     restart();
  311.     }
  312. }
  313.  
  314. drawscene(how)
  315. long how;
  316. {
  317.     char c[4];
  318.     long ir, ig, ib;
  319.     long tmp;
  320.  
  321.     if(how & DRAW_BACK) {
  322.     drawback();
  323.     }
  324.     if(how & DRAW_CONTROLS) {
  325.     drawbut(butquit);
  326.     drawbut(butgamma);
  327.     drawbut(butcolor);
  328.     drawbut(butshadow);
  329.     drawbut(butbrightness);
  330.     drawbut(butsaturate);
  331.     drawbut(butduotone);
  332.     drawbut(butaddnoise);
  333.     drawbut(butquantize);
  334.     drawbut(butsharpen);
  335.     drawbut(butwrite);
  336.     drawbut(butshoworig);
  337.     drawbut(butrestart);
  338.         drawboldlabel("Pick from the images on the left.",CONX+10,RADIOY-1*RADIODY);
  339.     }
  340.     if(how & DRAW_IMAGES) {
  341.     percentdone(50.0);
  342.     showcur(inimage,0);
  343.     if(how & PROC_IMAGES)
  344.         showarray(inimage,curmode,1);
  345.     else
  346.         showarray(inimage,curmode,0);
  347.     percentdone(100.0);
  348.     }
  349. }
  350.  
  351. long lastmx, lastmy;
  352.  
  353. locatemouseevents(long mx, long my)
  354. {
  355.     if((mx == lastmx) && (my == lastmy))
  356.     return;
  357.     locatebut(butquit,mx,my);
  358.     locatebut(butgamma,mx,my);
  359.     locatebut(butcolor,mx,my);
  360.     locatebut(butshadow,mx,my);
  361.     locatebut(butbrightness,mx,my);
  362.     locatebut(butsaturate,mx,my);
  363.     locatebut(butduotone,mx,my);
  364.     locatebut(butaddnoise,mx,my);
  365.     locatebut(butquantize,mx,my);
  366.     locatebut(butsharpen,mx,my);
  367.     locatebut(butwrite,mx,my);
  368.     locatebut(butshoworig,mx,my);
  369.     locatebut(butrestart,mx,my);
  370. }
  371.  
  372. addop(mode,p1,p2,p3)
  373. int mode;
  374. float p1, p2, p3;
  375. {
  376.     func[nops] = mode;
  377.     args[nops][0] = p1;
  378.     args[nops][1] = p2;
  379.     args[nops][2] = p3;
  380.     nops++;
  381.     if(nops == MAXSTEPS) {
  382.     nops--;
  383.     fprintf(stderr,"nops exceed %d\n",MAXSTEPS);
  384.     return;
  385.     }
  386. }
  387.  
  388. applytoimage(inname,outname)
  389. char *inname, *outname;
  390. {
  391.     int ixsize, iysize, izsize, i, y;
  392.     int r, sr, nr, nrows, oy, border;
  393.     IMAGE *iimage, *oimage;
  394.     short *rbuf, *gbuf, *bbuf;
  395.     unsigned long *lbuf, *tbuf;
  396.     float p1, p2, p3;
  397.     canvas scan, dcan;
  398.     int mat[3][3];
  399.  
  400. /* open the input image file */
  401.     iimage = iopen(inname,"r");
  402.     if(!iimage) {
  403.     fprintf(stderr,"applytoimage: can't open input image %s\n",inname);
  404.     return;
  405.     }
  406.     ixsize = iimage->xsize;
  407.     iysize = iimage->ysize;
  408.     izsize = iimage->zsize;
  409.     oimage = iopen(outname,"w",RLE(1),3,ixsize,iysize,3);
  410.  
  411. /* see the width of the border that is needed */
  412.     border = 0;
  413.     for(i=0; i<nops; i++) {
  414.     if(func[i] == MODE_SHARPEN)
  415.         border++;
  416.     }
  417.  
  418. /* figure out how many rows to do each pass */
  419.     nrows = 40;
  420.     if(nrows<4*border)
  421.     nrows = 4*border;
  422.  
  423. /* malloc buffers */
  424.     rbuf = (short *)malloc(ixsize*sizeof(short));
  425.     gbuf = (short *)malloc(ixsize*sizeof(short));
  426.     bbuf = (short *)malloc(ixsize*sizeof(short));
  427.     lbuf = (unsigned long *)malloc(ixsize*sizeof(long)*nrows);
  428.     tbuf = (unsigned long *)malloc(ixsize*sizeof(long)*nrows);
  429.  
  430. /* read and transform the image */
  431.     oy = 0;
  432.     y = 0;
  433.     percentdone(0.0);
  434.     while(1) {
  435.  
  436. /* read image data */
  437.     nr = 0;
  438.     for(i=0; i<nrows; i++) {
  439.         getrow(iimage,rbuf,y,0%izsize);
  440.         getrow(iimage,gbuf,y,1%izsize);
  441.         getrow(iimage,bbuf,y,2%izsize);
  442.         rgbtocpack(rbuf,gbuf,bbuf,lbuf+nr*ixsize,ixsize);
  443.         y++;
  444.         nr++;
  445.         if(y == iysize)
  446.          break;
  447.     }
  448.  
  449. /* process a block of rows */
  450.     for(i=0; i<nops; i++) {
  451.         p1 = args[i][0];
  452.         p2 = args[i][1];
  453.         p3 = args[i][2];
  454.         switch(func[i]) {
  455.         case MODE_GAMMA:
  456.             gammaop(lbuf,nr*ixsize,p1);
  457.             break;
  458.         case MODE_COLOR:
  459.             cscaleop(lbuf,nr*ixsize,p1,p2,p3);
  460.             break;
  461.         case MODE_SHADOW:
  462.             imgexpop(lbuf,nr*ixsize,p1,p2);
  463.             break;
  464.         case MODE_HIGHLIGHT:
  465.             imgexpop(lbuf,nr*ixsize,p1,p2);
  466.             break;
  467.         case MODE_SATURATE:
  468.             saturateop(lbuf,nr*ixsize,p1);
  469.             break;
  470.         case MODE_DUOTONE:
  471.             duotoneop(lbuf,nr*ixsize,p1,p2,p3);
  472.             break;
  473.         case MODE_ADDNOISE:
  474.             addnoiseop(lbuf,nr*ixsize,p1);
  475.             break;
  476.         case MODE_QUANTIZE:
  477.             quantop(lbuf,nr*ixsize,p1);
  478.             break;
  479.         case MODE_SHARPEN:
  480.             scan.data = lbuf;
  481.             scan.xsize = ixsize;
  482.             scan.ysize = nr;
  483.             scan.flushfunc = 0;
  484.             dcan.data = tbuf;
  485.             dcan.xsize = ixsize;
  486.             dcan.ysize = nr;
  487.             dcan.flushfunc = 0;
  488.             blurcanvas(&scan,&dcan);
  489.             blendcanvas(&scan,&dcan,&dcan,-p1);
  490.             bcopy(tbuf,lbuf,nr*ixsize*sizeof(long));
  491.             break;
  492.         }
  493.     }
  494.     if(oy == 0)
  495.         sr = 0;
  496.     else
  497.         sr = border;
  498.     if(y != iysize)
  499.         nr -= border;
  500.     for(r=sr; r<nr; r++) {
  501.         cpacktorgb(lbuf+ixsize*r,rbuf,gbuf,bbuf,ixsize);
  502.         putrow(oimage,rbuf,oy,0);
  503.         putrow(oimage,gbuf,oy,1);
  504.         putrow(oimage,bbuf,oy,2);
  505.         oy++;
  506.     }
  507.     if(oy == iysize) 
  508.         break;
  509.     percentdone(100.0*y/(iysize-1));
  510.     y = oy-border;
  511.     }
  512.     percentdone(100.0);
  513.     iclose(iimage);
  514.     iclose(oimage);
  515.     free(rbuf);
  516.     free(gbuf);
  517.     free(bbuf);
  518.     free(lbuf);
  519.     free(tbuf);
  520. }
  521.  
  522. inimages(mx,my,val)
  523. int mx, my, val;
  524. {
  525.     if(mx<CONX && my < WINYSIZE) {
  526.     if(val != UIBUTTONDOWN)
  527.         return 1;
  528.     percentdone(50.0);
  529.     new = applyprocess(inimage,curmode,mx,my);
  530.     freecanvas(inimage);
  531.     inimage = new;
  532.     showcur(inimage,1);
  533.     showarray(inimage,curmode,1);
  534.     percentdone(100.0);
  535.     return 1;
  536.     } else {
  537.     return 0;
  538.     }
  539. }
  540.  
  541. drawback()
  542. {
  543.     cpack(BACKCOLOR);
  544.     clear();
  545.     cpack(BLACKCOLOR);
  546.     move2i(CONX,5);
  547.     draw2i(CONX,WINYSIZE-5);
  548. }
  549.  
  550. writecanvas(c,x,y)
  551. canvas *c;
  552. int x, y;
  553. {
  554.     lrectwrite(x,y,x+c->xsize-1,y+c->ysize-1,c->data);
  555. }
  556.  
  557. clearrect(c,x,y,off)
  558. canvas *c;
  559. int x, y, off;
  560. {
  561.     rectfi(x-off,y-off,x+c->xsize-1+off,y+c->ysize-1+off);
  562. }
  563.  
  564. outlinerect(c,x,y,off)
  565. canvas *c;
  566. int x, y, off;
  567. {
  568.     recti(x-off,y-off,x+c->xsize-1+off,y+c->ysize-1+off);
  569. }
  570.  
  571. canvas *tempimg;
  572.  
  573. processcanvas(c,pc,mode,fx,fy,f,saveop,newimg)
  574. canvas *c, *pc;
  575. int mode;
  576. float fx , fy, f;
  577. int saveop, newimg;
  578. {
  579.     float p1, p2, p3;
  580.  
  581.     p1 = p2 = p3 = 0.0;
  582.     canvascopy(c,pc);
  583.     switch(mode) {
  584.     case MODE_GAMMA:
  585.         p1 = flerp(0.5,2.0,f);
  586.         canvasop(pc,gammaop,p1);
  587.         break;
  588.     case MODE_COLOR:
  589.         pptorgb(fx,fy,CBALSCALE,&p1,&p2,&p3);
  590.         canvasop(pc,cscaleop,p1,p2,p3);
  591.         break;
  592.     case MODE_SHADOW:
  593.         p1 = flerp(-0.2,0.2,f);
  594.         p2 = 1.0;
  595.         canvasop(pc,imgexpop,p1,p2);
  596.         break;
  597.     case MODE_HIGHLIGHT:
  598.         p1 = 0.0;
  599.         p2 = flerp(1.4,0.6,f);
  600.         canvasop(pc,imgexpop,p1,p2);
  601.         break;
  602.     case MODE_SATURATE:
  603.         p1 = 2.0*f;
  604.         if(p1<0.0)
  605.         p1 = 0;
  606.         canvasop(pc,saturateop,p1);
  607.         break;
  608.     case MODE_DUOTONE:
  609.         pptorgb(fx,fy,DUOTONESCALE,&p1,&p2,&p3);
  610.         canvasop(pc,duotoneop,p1,p2,p3);
  611.         break;
  612.     case MODE_ADDNOISE:
  613.         p1 = f;
  614.         canvasop(pc,addnoiseop,p1);
  615.         break;
  616.     case MODE_QUANTIZE:
  617.         p1 = flerp(2.0,10.0,f);
  618.         canvasop(pc,quantop,p1);
  619.         break;
  620.     case MODE_SHARPEN:
  621.         if(newimg) {
  622.         if(tempimg)
  623.             freecanvas(tempimg);
  624.         tempimg = newcanvas(c->xsize,c->ysize);
  625.         blurcanvas(c,tempimg);
  626.         }
  627.         p1 = flerp(0.0,3.0,f);
  628.         if(p1<0.0)
  629.         p1 = 0.0;
  630.         blendcanvas(c,tempimg,pc,-p1);
  631.         break;
  632.     }
  633.     if(saveop)
  634.     addop(mode,p1,p2,p3);
  635. }
  636.  
  637. canvas *applyprocess(c,mode,mx,my)
  638. int mode, mx, my;
  639. {
  640.     float fx, fy, f;
  641.     canvas *pc;
  642.  
  643.     fx = 0.5+(mx-CONX/2)/(float)(2*STDSKIP);
  644.     fy = 0.5+(my-CONX/2)/(float)(2*STDSKIP);
  645.     fy = 1.0-fy;
  646.     if(my>2*STDSKIP+STDSPACE/2)
  647.     f = 0*CONX+mx;
  648.     else if(my<1*STDSKIP+STDSPACE/2)
  649.     f = 2*CONX+mx;
  650.     else 
  651.     f = 1*CONX+mx;
  652.     f = ((9.0*f/(3*CONX))-0.5)/8.0;
  653.     pc = clonecanvas(c);
  654.     processcanvas(c,pc,mode,fx,fy,f,1,1);
  655.     return pc;
  656. }
  657.  
  658. pptorgb(fx,fy,mag,r,g,b)
  659. float fx, fy, mag;
  660. float *r, *g, *b;
  661. {
  662.     float min, max;
  663.  
  664.     *r = 1.0+mag*(fx-0.5);
  665.     *g = 1.0;
  666.     *b = 1.0+mag*(fy-0.5);
  667.     min = *r;
  668.     if(*g<min)
  669.         min = *g;
  670.     if(*b<min)
  671.         min = *b;
  672.     *r = *r/min;
  673.     *g = *g/min;
  674.     *b = *b/min;
  675. }
  676.  
  677. canvas *cor;
  678.  
  679. showcur(c,flash)
  680. canvas *c;
  681. {
  682.     int xoff, yoff;
  683.  
  684.     xoff = (STDSIZE-c->xsize)/2+15;
  685.     yoff = (STDSIZE-c->ysize)/2-10;
  686.     if(!cor)
  687.     cor = clonecanvas(c);
  688.     else
  689.     canvascopy(c,cor);
  690.     writecanvas(cor,xoff+CONX+STDSPACE,yoff+WINYSIZE-STDSKIP);
  691.     if(flash) {
  692.     linewidth(2);
  693.     cpack(REDCOLOR);
  694.     outlinerect(c,xoff+CONX+STDSPACE,yoff+WINYSIZE-STDSKIP,4);
  695.     sginap(20);
  696.     cpack(BACKCOLOR);
  697.     outlinerect(c,xoff+CONX+STDSPACE,yoff+WINYSIZE-STDSKIP,4);
  698.     linewidth(1);
  699.     }
  700.     cpack(BLACKCOLOR);
  701.     outlinerect(c,xoff+CONX+STDSPACE,yoff+WINYSIZE-STDSKIP,4);
  702. }
  703.  
  704. cleararray()
  705. {
  706.     cpack(BACKCOLOR);
  707.     rectfi(0,0,CONX-5,WINYSIZE);
  708. }
  709.  
  710. canvas *smallcan[3][3];
  711.  
  712. showarray(c,mode,doproc)
  713. canvas *c;
  714. int mode, doproc;
  715. {
  716.     int x, y;
  717.     canvas *pc;
  718.     float fx, fy, f;
  719.     int xoff, yoff, xdel;
  720.     int newimg;
  721.  
  722.     if(!smallcan[0][0]) {
  723.     for(y=0; y<3; y++)
  724.         for(x=0; x<3; x++)
  725.          smallcan[y][x] = clonecanvas(c);
  726.     }
  727.     xoff = (STDSIZE-c->xsize)/2;
  728.     yoff = (STDSIZE-c->ysize)/2;
  729.     f = 0.0;
  730.     if(mode == MODE_COLOR || mode == MODE_DUOTONE) {
  731.     cpack(BLACKCOLOR);
  732.     move2i(1*STDSKIP+STDSPACE/2,5);
  733.     draw2i(1*STDSKIP+STDSPACE/2,WINYSIZE-5);
  734.     move2i(2*STDSKIP+STDSPACE/2,5);
  735.     draw2i(2*STDSKIP+STDSPACE/2,WINYSIZE-5);
  736.     } else {
  737.     cpack(BACKCOLOR);
  738.     move2i(1*STDSKIP+STDSPACE/2,5);
  739.     draw2i(1*STDSKIP+STDSPACE/2,WINYSIZE-5);
  740.     move2i(2*STDSKIP+STDSPACE/2,5);
  741.     draw2i(2*STDSKIP+STDSPACE/2,WINYSIZE-5);
  742.     }
  743.     cpack(BLACKCOLOR);
  744.     move2i(5,1*STDSKIP+STDSPACE/2);
  745.     draw2i(CONX-5,1*STDSKIP+STDSPACE/2);
  746.     move2i(5,2*STDSKIP+STDSPACE/2);
  747.     draw2i(CONX-5,2*STDSKIP+STDSPACE/2);
  748.  
  749.     cpack(BACKCOLOR);
  750.     for(y=0; y<3; y++) {
  751.     for(x=0; x<3; x++) {
  752.         clearrect(c,xoff+STDSPACE+x*STDSKIP,yoff+STDSPACE+(2-y)*STDSKIP,2);
  753.     }
  754.     }
  755.     for(y=0; y<3; y++) {
  756.     for(x=0; x<3; x++) {
  757.         if(doproc) {
  758.         if(x==0 && y==0)
  759.             newimg = 1;
  760.         else
  761.             newimg = 0;
  762.         processcanvas(c,smallcan[y][x],mode,x/2.0,y/2.0,(y*3+x)/8.0,0,newimg);
  763.         }
  764.         writecanvas(smallcan[y][x],xoff+STDSPACE+x*STDSKIP,yoff+STDSPACE+(2-y)*STDSKIP);
  765.     }
  766.     }
  767. }
  768.  
  769. blurcanvas(s,d)
  770. canvas *s, *d;
  771. {
  772.     int mat[3][3];
  773.  
  774.     mat[0][0] = 2; mat[0][1] = 2; mat[0][2] = 2;
  775.     mat[1][0] = 2; mat[1][1] = 2; mat[1][2] = 2;
  776.     mat[2][0] = 2; mat[2][1] = 2; mat[2][2] = 2;
  777.     convolve3(s,d,mat);
  778. }
  779.  
  780. sharpenkernel(mat,mag)
  781. int mat[3][3];
  782. float mag;
  783. {
  784.     float blur, sharp;
  785.     int neg, pos;
  786.  
  787.     blur = 1.0/9.0;
  788.     sharp = 1.0;
  789.     neg = 1024*flerp(0.0,blur,-mag);
  790.     pos = 1024*flerp(1.0,blur,-mag);
  791.  
  792.     mat[0][0] = neg; mat[0][1] = neg; mat[0][2] = neg;
  793.     mat[1][0] = neg; mat[1][1] = pos; mat[1][2] = neg;
  794.     mat[2][0] = neg; mat[2][1] = neg; mat[2][2] = neg;
  795. }
  796.  
  797. sharpen(s,d,mag)
  798. canvas *s, *d;
  799. float mag;
  800. {
  801.     int mat[3][3];
  802.  
  803.     sharpenkernel(mat,mag);
  804.     convolve3(s,d,mat);
  805. }
  806.  
  807.