home *** CD-ROM | disk | FTP | other *** search
/ Fractal Frenzy 1 / WalnutCreekFractalFrenzy-1.iso / pc / viewers / x11 / xv221.tz / xv221 / xv-2.21 / xvsmooth.c < prev    next >
C/C++ Source or Header  |  1992-02-27  |  18KB  |  666 lines

  1. /*
  2.  * xvsmooth.c - smoothing/color dither routines for XV
  3.  * 
  4.  *  Author:    John Bradley, University of Pennsylvania
  5.  *                (bradley@cis.upenn.edu)
  6.  *
  7.  *  Contains:
  8.  *            void  Smooth()
  9.  *            byte *Smooth24()
  10.  *     static int   SmoothX(pic24)
  11.  *     static int   SmoothY(pic24)
  12.  *     static int   SmoothXY(pic24)
  13.  *            void  ColorDither(pic24, w, h)
  14.  */
  15.  
  16.  
  17. /*
  18.  * Copyright 1989, 1990, 1991, 1992 by John Bradley and
  19.  *                       The University of Pennsylvania
  20.  *
  21.  * Permission to use, copy, and distribute for non-commercial purposes,
  22.  * is hereby granted without fee, providing that the above copyright
  23.  * notice appear in all copies and that both the copyright notice and this
  24.  * permission notice appear in supporting documentation.
  25.  *
  26.  * The software may be modified for your own purposes, but modified versions
  27.  * may not be distributed.
  28.  *
  29.  * This software is provided "as is" without any expressed or implied warranty.
  30.  *
  31.  * The author may be contacted via:
  32.  *    US Mail:   John Bradley
  33.  *               GRASP Lab, Room 301C
  34.  *               3401 Walnut St.
  35.  *               Philadelphia, PA  19104
  36.  *
  37.  *    Phone:     (215) 898-8813
  38.  *    EMail:     bradley@cis.upenn.edu
  39.  */
  40.  
  41.  
  42. #include "xv.h"
  43.  
  44. #ifdef __STDC__
  45. static int SmoothX(byte *);
  46. static int SmoothY(byte *);
  47. static int SmoothXY(byte *);
  48. #else
  49. static int  SmoothX(), SmoothY(), SmoothXY();
  50. #endif
  51.  
  52.  
  53. /***************************************************/
  54. void Smooth()
  55. {
  56.   /* does a SMOOTH resize from cpic into a eWIDE*eHIGH epic.  
  57.      Generates a smooth 24bit eWIDE*eHIGH image, calls ColorDither()
  58.      to map it onto the screen, then throws away 24-bit version */
  59.  
  60.   byte *pic24;
  61.  
  62.   pic24 = Smooth24();
  63.   if (pic24) {
  64.     epicmode = EM_SMOOTH;   SetEpicMode();
  65.     ColorDither(pic24, eWIDE, eHIGH);
  66.     free(pic24);
  67.   }
  68. }
  69.  
  70.  
  71.  
  72.  
  73. /***************************************************/
  74. byte *Smooth24()
  75. {
  76.   /* does a SMOOTH resize from cpic into a eWIDE*eHIGH epic.  
  77.      Generates a smooth 24bit eWIDE*eHIGH image.  Returns NULL if
  78.      it can't (failed malloc, no doubt) */
  79.  
  80.   byte *pic24, *pp;
  81.   int *cxtab, *pxtab;
  82.   int y1cWIDE, cycWIDE;
  83.   int ex, ey, cx, cy, px, py, apx, apy, x1, y1;
  84.   int cA, cB, cC, cD;
  85.   int pA, pB, pC, pD;
  86.   int retval;
  87.  
  88.   pp = pic24 = (byte *) malloc(eWIDE * eHIGH * 3);
  89.   if (!pic24) {
  90.     fprintf(stderr,"unable to malloc in 'Smooth24()'\n");
  91.     return NULL;
  92.   }
  93.  
  94.   retval = 0;
  95.  
  96.   /* decide which smoothing routine to use based on type of expansion */
  97.   if      (eWIDE <  cWIDE && eHIGH <  cHIGH) retval = SmoothXY(pic24);
  98.   else if (eWIDE <  cWIDE && eHIGH >= cHIGH) retval = SmoothX(pic24);
  99.   else if (eWIDE >= cWIDE && eHIGH <  cHIGH) retval = SmoothY(pic24);
  100.   else {
  101.     /* eWIDE >= cWIDE && eHIGH >= cHIGH */
  102.     /* cx,cy = original pixel in cpic.  px,py = relative position 
  103.        of pixel ex,ey inside of cx,cy as percentages +-50%, +-50%.  
  104.        0,0 = middle of pixel */
  105.  
  106.     /* we can save a lot of time by precomputing cxtab[] and pxtab[], both
  107.        arrays of eWIDE ints that contain values for the equations:
  108.          cx = (ex * cWIDE) / eWIDE;
  109.          px = ((ex * cWIDE * 100) / eWIDE) - (cx * 100) - 50; */
  110.  
  111.     cxtab = (int *) malloc(eWIDE * sizeof(int));
  112.     if (!cxtab) { free(pic24);  return NULL; }
  113.  
  114.     pxtab = (int *) malloc(eWIDE * sizeof(int));
  115.     if (!pxtab) { free(pic24);  free(cxtab);  return NULL; }
  116.  
  117.     for (ex=0; ex<eWIDE; ex++) {
  118.       cxtab[ex] = (ex * cWIDE) / eWIDE;
  119.       pxtab[ex] = (((ex * cWIDE)* 100) / eWIDE) 
  120.                - (cxtab[ex] * 100) - 50;
  121.     }
  122.     
  123.     for (ey=0; ey<eHIGH; ey++) {
  124.       cy = (ey * cHIGH) / eHIGH;
  125.       py = (((ey * cHIGH) * 100) / eHIGH) - (cy * 100) - 50;
  126.       if (py<0) { y1 = cy-1;  if (y1<0) y1=0; }
  127.            else { y1 = cy+1;  if (y1>cHIGH-1) y1=cHIGH-1; }
  128.  
  129.       y1cWIDE = y1 * cWIDE;
  130.       cycWIDE = cy * cWIDE;
  131.  
  132.       if ((ey&15) == 0) WaitCursor();
  133.  
  134.       for (ex=0; ex<eWIDE; ex++) {
  135.     cx = cxtab[ex];
  136.     px = pxtab[ex];
  137.  
  138.     if (px<0) { x1 = cx-1;  if (x1<0) x1=0; }
  139.          else { x1 = cx+1;  if (x1>cWIDE-1) x1=cWIDE-1; }
  140.  
  141.     cA = cpic[y1cWIDE + x1];
  142.     cB = cpic[y1cWIDE + cx];
  143.     cC = cpic[cycWIDE + x1];
  144.     cD = cpic[cycWIDE + cx];
  145.  
  146.     /* quick check */
  147.     if (cA == cB && cB == cC && cC == cD) {
  148.       /* set this pixel to the same color as in cpic */
  149.       *pp++ = r[cD];  *pp++ = g[cD];  *pp++ = b[cD];
  150.     }
  151.  
  152.     else {
  153.       /* compute weighting factors */
  154.       apx = abs(px);  apy = abs(py);
  155.       pA = (apx * apy) / 100;
  156.       pB = (apy * (100 - apx)) / 100;
  157.       pC = (apx * (100 - apy)) / 100;
  158.       pD = 100 - (pA + pB + pC);
  159.  
  160.       *pp++ = (pA * r[cA])/100 + (pB * r[cB])/100 + 
  161.               (pC * r[cC])/100 + (pD * r[cD])/100;
  162.  
  163.       *pp++ = (pA * g[cA])/100 + (pB * g[cB])/100 + 
  164.               (pC * g[cC])/100 + (pD * g[cD])/100;
  165.  
  166.       *pp++ = (pA * b[cA])/100 + (pB * b[cB])/100 + 
  167.               (pC * b[cC])/100 + (pD * b[cD])/100;
  168.     }
  169.       }
  170.     }
  171.  
  172.   free(cxtab);  
  173.   free(pxtab);
  174.   }
  175.  
  176.   if (retval) {  /* failed */
  177.     free(pic24);
  178.     pic24 = (byte *) NULL;
  179.   }
  180.  
  181.   return pic24;
  182. }
  183.  
  184.  
  185.  
  186.  
  187. /***************************************************/
  188. static int SmoothX(pic24)
  189. byte *pic24;
  190. {
  191.   byte *cptr, *cptr1;
  192.   int  i, j;
  193.   int  *lbufR, *lbufG, *lbufB;
  194.   int  pixR, pixG, pixB;
  195.   int  pcnt0, pcnt1, lastpix, pixcnt, thisline, ypcnt;
  196.   int  *pixarr, *paptr;
  197.  
  198.   /* returns '0' if okay, '1' if failed (malloc) */
  199.  
  200.   /* for case where cpic is shrunk horizontally and stretched vertically
  201.      shrinks cpic into an eWIDExeHIGH 24-bit picture.  Only works correctly
  202.      when cWIDE>=eWIDE and cHIGH<=eHIGH */
  203.  
  204.   lbufR = (int *) calloc(cWIDE, sizeof(int));
  205.   if (!lbufR) return 1;
  206.   lbufG = (int *) calloc(cWIDE, sizeof(int));
  207.   if (!lbufG) { free(lbufR); return 1; }
  208.   lbufB = (int *) calloc(cWIDE, sizeof(int));
  209.   if (!lbufB) { free(lbufG);  free(lbufR); return 1; }
  210.  
  211.   pixarr = (int *) calloc(cWIDE+1, sizeof(int));
  212.   if (!pixarr) { free(lbufB);  free(lbufG);  free(lbufR); return 1; }
  213.   
  214.   for (j=0; j<=cWIDE; j++) 
  215.     pixarr[j] = (j*eWIDE + (15*cWIDE)/16) / cWIDE;
  216.  
  217.   cptr = cpic;  cptr1 = cptr + cWIDE;
  218.  
  219.   for (i=0; i<eHIGH; i++) {
  220.     if ((i&15) == 0) WaitCursor();
  221.  
  222.     ypcnt = (((i*cHIGH)<<6) / eHIGH) - 32;
  223.     if (ypcnt<0) ypcnt = 0;
  224.  
  225.     pcnt1 = ypcnt & 0x3f;                     /* 64ths of NEXT line to use */
  226.     pcnt0 = 64 - pcnt1;                       /* 64ths of THIS line to use */
  227.  
  228.     thisline = ypcnt>>6;
  229.  
  230.     cptr  = cpic + thisline * cWIDE;
  231.     if (thisline+1 < cHIGH) cptr1 = cptr + cWIDE;
  232.     else cptr1 = cptr;
  233.  
  234.     for (j=0; j<cWIDE; j++, cptr++, cptr1++) {
  235.       lbufR[j] = ((r[*cptr] * pcnt0) + (r[*cptr1] * pcnt1)) >> 6;
  236.       lbufG[j] = ((g[*cptr] * pcnt0) + (g[*cptr1] * pcnt1)) >> 6;
  237.       lbufB[j] = ((b[*cptr] * pcnt0) + (b[*cptr1] * pcnt1)) >> 6;
  238.     }
  239.  
  240.     pixR = pixG = pixB = pixcnt = lastpix = 0;
  241.  
  242.     for (j=0, paptr=pixarr; j<=cWIDE; j++,paptr++) {
  243.       if (*paptr != lastpix) {   /* write a pixel to pic24 */
  244.     *pic24++ = pixR / pixcnt;
  245.     *pic24++ = pixG / pixcnt;
  246.     *pic24++ = pixB / pixcnt;
  247.     lastpix = *paptr;
  248.     pixR = pixG = pixB = pixcnt = 0;
  249.       }
  250.  
  251.       if (j<cWIDE) {
  252.     pixR += lbufR[j];
  253.     pixG += lbufG[j];
  254.     pixB += lbufB[j];
  255.     pixcnt++;
  256.       }
  257.     }
  258.   }
  259.  
  260.   free(lbufR);  free(lbufG);  free(lbufB);  free(pixarr);
  261.   return 0;
  262. }
  263.  
  264.     
  265.       
  266.  
  267.  
  268.  
  269. /***************************************************/
  270. static int SmoothY(pic24)
  271. byte *pic24;
  272. {
  273.   byte *clptr, *cptr, *cptr1;
  274.   int  i, j;
  275.   int  *lbufR, *lbufG, *lbufB, *pct0, *pct1, *cxarr, *cxptr;
  276.   int  lastline, thisline, linecnt;
  277.   int  retval;
  278.  
  279.  
  280.   /* returns '0' if okay, '1' if failed (malloc) */
  281.  
  282.   /* for case where cpic is shrunk vertically and stretched horizontally
  283.      shrinks cpic into an eWIDExeHIGH 24-bit picture.  Only works correctly
  284.      when cWIDE<=eWIDE and cHIGH>=eHIGH */
  285.  
  286.   retval = 0;   /* no probs, yet... */
  287.  
  288.   lbufR = lbufG = lbufB = pct0 = pct1 = cxarr = NULL;
  289.   lbufR = (int *) calloc(eWIDE, sizeof(int));
  290.   lbufG = (int *) calloc(eWIDE, sizeof(int));
  291.   lbufB = (int *) calloc(eWIDE, sizeof(int));
  292.   pct0  = (int *) calloc(eWIDE, sizeof(int));
  293.   pct1  = (int *) calloc(eWIDE, sizeof(int));
  294.   cxarr = (int *) calloc(eWIDE, sizeof(int));
  295.  
  296.   if (!lbufR || !lbufG || !lbufB || !pct0 || ! pct1 || !cxarr)
  297.     { retval = 1;  goto smyexit; }
  298.  
  299.  
  300.  
  301.   for (i=0; i<eWIDE; i++) {                /* precompute some handy tables */
  302.     int cx64;
  303.     cx64 = (((i * cWIDE) << 6) / eWIDE) - 32;
  304.     if (cx64<0) cx64 = 0;
  305.     pct1[i] = cx64 & 0x3f;
  306.     pct0[i] = 64 - pct1[i];
  307.     cxarr[i] = cx64 >> 6;
  308.   }
  309.  
  310.  
  311.   lastline = linecnt = 0;
  312.  
  313.   for (i=0, clptr=cpic; i<=cHIGH; i++, clptr+=cWIDE) {
  314.     if ((i&15) == 0) WaitCursor();
  315.  
  316.     thisline = (i * eHIGH + (15*cHIGH)/16) / cHIGH;
  317.     if (thisline != lastline) {  /* copy a line to pic24 */
  318.  
  319.       for (j=0; j<eWIDE; j++) {
  320.     *pic24++ = lbufR[j] / linecnt;
  321.     *pic24++ = lbufG[j] / linecnt;
  322.     *pic24++ = lbufB[j] / linecnt;
  323.       }
  324.  
  325.       bzero( (char *) lbufR, eWIDE * sizeof(int));  /* clear out line bufs */
  326.       bzero( (char *) lbufG, eWIDE * sizeof(int));
  327.       bzero( (char *) lbufB, eWIDE * sizeof(int));
  328.       linecnt = 0;  lastline = thisline;
  329.     }
  330.  
  331.     for (j=0, cxptr=cxarr; j<eWIDE; j++, cxptr++) {
  332.       cptr  = clptr + *cxptr;
  333.       if (*cxptr < cWIDE-1) cptr1 = cptr + 1;
  334.                        else cptr1 = cptr;
  335.  
  336.       lbufR[j] += (((r[*cptr] * pct0[j]) + (r[*cptr1] * pct1[j])) >> 6);
  337.       lbufG[j] += (((g[*cptr] * pct0[j]) + (g[*cptr1] * pct1[j])) >> 6);
  338.       lbufB[j] += (((b[*cptr] * pct0[j]) + (b[*cptr1] * pct1[j])) >> 6);
  339.     }
  340.    
  341.     linecnt++;
  342.   }
  343.  
  344.  
  345.  smyexit:
  346.   if (lbufR) free(lbufR);
  347.   if (lbufG) free(lbufG);
  348.   if (lbufB) free(lbufB);
  349.   if (pct0)  free(pct0);
  350.   if (pct1)  free(pct1);
  351.   if (cxarr) free(cxarr);
  352.  
  353.   return retval;
  354. }
  355.  
  356.     
  357.       
  358.  
  359.  
  360.  
  361. /***************************************************/
  362. static int SmoothXY(pic24)
  363. byte *pic24;
  364. {
  365.   byte *cptr;
  366.   int  i,j;
  367.   int  *lbufR, *lbufG, *lbufB;
  368.   int  pixR, pixG, pixB;
  369.   int  lastline, thisline, lastpix, linecnt, pixcnt;
  370.   int  *pixarr, *paptr;
  371.  
  372.  
  373.   /* returns '0' if okay, '1' if failed (malloc) */
  374.  
  375.   /* shrinks cpic into an eWIDExeHIGH 24-bit picture.  Only works correctly
  376.      when cWIDE>=eWIDE and cHIGH>=eHIGH (ie, the picture is shrunk on both
  377.      axes) */
  378.  
  379.   lbufR = (int *) calloc(cWIDE, sizeof(int));
  380.   if (!lbufR) return 1;
  381.   lbufG = (int *) calloc(cWIDE, sizeof(int));
  382.   if (!lbufG) { free(lbufR); return 1; }
  383.   lbufB = (int *) calloc(cWIDE, sizeof(int));
  384.   if (!lbufB) { free(lbufG);  free(lbufR); return 1; }
  385.  
  386.   pixarr = (int *) calloc(cWIDE+1, sizeof(int));
  387.   if (!pixarr) { free(lbufB);  free(lbufG);  free(lbufR); return 1; }
  388.   
  389.   for (j=0; j<=cWIDE; j++) 
  390.     pixarr[j] = (j*eWIDE + (15*cWIDE)/16) / cWIDE;
  391.  
  392.   lastline = linecnt = pixR = pixG = pixB = 0;
  393.   cptr = cpic;
  394.  
  395.   for (i=0; i<=cHIGH; i++) {
  396.     if ((i&15) == 0) WaitCursor();
  397.  
  398.     thisline = (i * eHIGH + (15*cHIGH)/16 ) / cHIGH;
  399.  
  400.     if ((thisline != lastline)) {      /* copy a line to pic24 */
  401.       pixR = pixG = pixB = pixcnt = lastpix = 0;
  402.  
  403.       for (j=0, paptr=pixarr; j<=cWIDE; j++,paptr++) {
  404.     if (*paptr != lastpix) {                 /* write a pixel to pic24 */
  405.       *pic24++ = (pixR/linecnt) / pixcnt;
  406.       *pic24++ = (pixG/linecnt) / pixcnt;
  407.       *pic24++ = (pixB/linecnt) / pixcnt;
  408.       lastpix = *paptr;
  409.       pixR = pixG = pixB = pixcnt = 0;
  410.     }
  411.  
  412.     if (j<cWIDE) {
  413.       pixR += lbufR[j];
  414.       pixG += lbufG[j];
  415.       pixB += lbufB[j];
  416.       pixcnt++;
  417.     }
  418.       }
  419.       lastline = thisline;
  420.       bzero( (char *) lbufR, cWIDE * sizeof(int));  /* clear out line bufs */
  421.       bzero( (char *) lbufG, cWIDE * sizeof(int));
  422.       bzero( (char *) lbufB, cWIDE * sizeof(int));
  423.       linecnt = 0;
  424.     }
  425.  
  426.     if (i<cHIGH) {
  427.       for (j=0; j<cWIDE; j++, cptr++) {
  428.     lbufR[j] += r[*cptr];
  429.     lbufG[j] += g[*cptr];
  430.     lbufB[j] += b[*cptr];
  431.       }
  432.       linecnt++;
  433.     }
  434.   }
  435.  
  436.   free(lbufR);  free(lbufG);  free(lbufB);  free(pixarr);
  437.   return 0;
  438. }
  439.  
  440.     
  441.       
  442.  
  443.  
  444.  
  445. /********************************************/
  446. void ColorDither(pic24,w,h)
  447. byte *pic24;
  448. int   w,h;
  449. {
  450.   /* takes a 24 bit picture, of size w*h, dithers with the colors that 
  451.      have already been allocated, and sticks it's output in 'epic'.
  452.      Calls CreateXImage() and DrawWindow to display results
  453.  
  454.      if pic24 is NULL, uses the existing 'epic' (an 8-bit image) as
  455.      the source */
  456.  
  457.   byte *np, *ep, *newpic; 
  458.   short *cache;
  459.   int r2, g2, b2;
  460.   int *thisline, *nextline, *thisptr, *nextptr, *tmpptr;
  461.   int  i, j, rerr, gerr, berr, pwide3;
  462.   int  imax, jmax;
  463.   XColor ctab[256], *cptr;
  464.   int key;
  465.   long cnt1, cnt2;
  466.  
  467.   if (epicmode != EM_SMOOTH) {  /* don't set EM_DITH if called from Smooth() */
  468.     epicmode = EM_DITH;   SetEpicMode();
  469.   }
  470.  
  471.  
  472.   SetISTR(ISTR_EXPAND, "%.3g x %.3g  (%d x %d)",
  473.       ((float) w) / cWIDE, ((float) h) / cHIGH, w, h);
  474.  
  475.   /* if mono and we're given a 24-bit image, monoify it before attempting
  476.      to dither */
  477.   if ((mono || ncols==0) && pic24) {
  478.     for (i=w*h,np=pic24; i; i--, np+=3) {
  479.       j = MONO(np[0],np[1],np[2]);
  480.       np[0] = np[1] = np[2] = j;
  481.     }
  482.   }
  483.  
  484.  
  485.  
  486.   cnt1 = cnt2 = 0;
  487.   cache = (short *) calloc(2<<14, sizeof(short));
  488.   if (!cache) return;
  489.  
  490.   
  491.   /* load up ctab[] with the colors we'll be dithering with */
  492.  
  493.   if (theVisual->class == TrueColor || theVisual->class == DirectColor) {  
  494.     /* if truecolor, we have exactly the colors in the pic's colormap */
  495.     for (i=0; i<numcols; i++) {
  496.       ctab[i].red   = r[i];
  497.       ctab[i].green = g[i];
  498.       ctab[i].blue  = b[i];
  499.     }
  500.   }
  501.     
  502.   else if (ncols>0) {
  503.     /* read the colors currently being used in the colormap */
  504.     for (i=0; i<numcols; i++) ctab[i].pixel = cols[i];
  505.     XQueryColors(theDisp, (LocalCmap) ? LocalCmap : theCmap, ctab, numcols);
  506.  
  507.     /* downshift color defs to 8 bit R,G,B vals instead of 16 bit */
  508.     for (i=0; i<numcols; i++) 
  509.       { ctab[i].red >>= 8;  ctab[i].green >>= 8;  ctab[i].blue >>=8; }
  510.   }
  511.  
  512.   else {
  513.     /* ncols==0 case */
  514.     for (i=0; i<numcols; i++) {
  515.       ctab[i].red = ctab[i].green = ctab[i].blue = 
  516.     MONO(r[i],g[i],b[i]);
  517.     }
  518.   }
  519.  
  520.   if (!pic24) { w = eWIDE;  h = eHIGH;  ep = epic; }
  521.   else ep = pic24;
  522.  
  523.   newpic = (byte *) malloc(w * h);         /* create output 8-bit pic */
  524.   if (!newpic) { free(cache); return; }
  525.  
  526.   np = newpic;  pwide3 = w*3;  imax = h-1;  jmax = w-1;
  527.  
  528.   thisline = (int *) malloc(pwide3 * sizeof(int));
  529.   nextline = (int *) malloc(pwide3 * sizeof(int));
  530.   if (!thisline || !nextline)
  531.     FatalError("unable to allocate memory in ColorDither()");
  532.  
  533.   /* get first line of picture */
  534.   if (!pic24)
  535.     for (j=w, tmpptr=nextline; j; j--, ep++) {
  536.       *tmpptr++ = (int) r[*ep];
  537.       *tmpptr++ = (int) g[*ep];
  538.       *tmpptr++ = (int) b[*ep];
  539.     }
  540.   else
  541.     for (j=pwide3, tmpptr=nextline; j; j--, ep++) *tmpptr++ = (int) *ep;
  542.  
  543.  
  544.   for (i=0; i<h; i++) {
  545.     if ((i&15) == 0) WaitCursor();
  546.  
  547.     tmpptr = thisline;  thisline = nextline;  nextline = tmpptr;   /* swap */
  548.  
  549.     if (i!=imax) {  /* get next line */
  550.       if (!pic24)
  551.     for (j=w, tmpptr=nextline; j; j--, ep++) {
  552.       *tmpptr++ = (int) r[*ep];
  553.       *tmpptr++ = (int) g[*ep];
  554.       *tmpptr++ = (int) b[*ep];
  555.     }
  556.       else
  557.     for (j=pwide3, tmpptr=nextline; j; j--, ep++) *tmpptr++ = (int) *ep;
  558.     }
  559.  
  560.     /* dither a line */
  561.     for (j=0, thisptr=thisline, nextptr=nextline; j<w; j++,np++) {
  562.       int k, d, mind, closest;
  563.  
  564.       r2 = *thisptr++;  g2 = *thisptr++;  b2 = *thisptr++;
  565.  
  566.       /* map r2,g2,b2 components (could be outside 0..255 range) 
  567.      into 0..255 range */
  568.       
  569.       if (r2<0 || g2<0 || b2<0) {   /* are there any negatives in RGB? */
  570.     if (r2<g2) { if (r2<b2) k = 0; else k = 2; }
  571.     else { if (g2<b2) k = 1; else k = 2; }
  572.  
  573.     switch (k) {
  574.     case 0:  g2 -= r2;  b2 -= r2;  d = (abs(r2) * 3) / 2;    /* RED */
  575.              r2 = 0;  
  576.              g2 = (g2>d) ? g2 - d : 0;
  577.              b2 = (b2>d) ? b2 - d : 0;
  578.              break;
  579.  
  580.     case 1:  r2 -= g2;  b2 -= g2;  d = (abs(g2) * 3) / 2;    /* GREEN */
  581.              r2 = (r2>d) ? r2 - d : 0;
  582.              g2 = 0;  
  583.              b2 = (b2>d) ? b2 - d : 0;
  584.              break;
  585.  
  586.     case 2:  r2 -= b2;  g2 -= b2;  d = (abs(b2) * 3) / 2;    /* BLUE */
  587.              r2 = (r2>d) ? r2 - d : 0;
  588.              g2 = (g2>d) ? g2 - d : 0;
  589.              b2 = 0;  
  590.              break;
  591.     }
  592.       }
  593.  
  594.       if (r2>255 || g2>255 || b2>255) {   /* any overflows in RGB */
  595.     if (r2>g2) { if (r2>b2) k = 0; else k = 2; }
  596.               else { if (g2>b2) k = 1; else k = 2; }
  597.  
  598.     switch (k) {
  599.     case 0:   g2 = (g2*255)/r2;  b2 = (b2*255)/r2;  r2=255;  break;
  600.     case 1:   r2 = (r2*255)/g2;  b2 = (b2*255)/g2;  g2=255;  break;
  601.     case 2:   r2 = (r2*255)/b2;  g2 = (g2*255)/b2;  b2=255;  break;
  602.     }
  603.       }
  604.  
  605.       key = ((r2&0xf8)<<6) | ((g2&0xf8)<<1) | (b2>>4);
  606.  
  607.       if (cache[key]) { *np = (byte) (cache[key] - 1);  cnt1++;    }
  608.       else {
  609.     /* not in cache, have to search the colortable */
  610.     cnt2++;
  611.  
  612.         mind = 10000;
  613.     for (k=closest=0, cptr=ctab; k<numcols && mind>7; k++,cptr++) {
  614.       d = abs(r2 - cptr->red)
  615.         + abs(g2 - cptr->green) 
  616.         + abs(b2 - cptr->blue);
  617.       if (d<mind) { mind = d;  closest = k; }
  618.     }
  619.     cache[key] = closest + 1;
  620.     *np = closest;
  621.       }
  622.  
  623.  
  624.       /* propogate the error */
  625.       rerr = r2 - ctab[*np].red;
  626.       gerr = g2 - ctab[*np].green;
  627.       berr = b2 - ctab[*np].blue;
  628.  
  629.       if (j!=jmax) {  /* adjust RIGHT pixel */
  630.     thisptr[0] += (rerr*7)/16;
  631.     thisptr[1] += (gerr*7)/16;
  632.     thisptr[2] += (berr*7)/16;
  633.       }
  634.       
  635.       if (i!=imax) {    /* do BOTTOM pixel */
  636.     nextptr[0] += (rerr*5)/16;
  637.     nextptr[1] += (gerr*5)/16;
  638.     nextptr[2] += (berr*5)/16;
  639.  
  640.     if (j>0) {  /* do BOTTOM LEFT pixel */
  641.       nextptr[-3] += (rerr*3)/16;
  642.       nextptr[-2] += (gerr*3)/16;
  643.       nextptr[-1] += (berr*3)/16;
  644.     }
  645.  
  646.     if (j!=jmax) {  /* do BOTTOM RIGHT pixel */
  647.       nextptr[3] += rerr/16;
  648.       nextptr[4] += gerr/16;
  649.       nextptr[5] += berr/16;
  650.     }
  651.     nextptr += 3;
  652.       }
  653.     }
  654.   }
  655.  
  656.   if (epic!=cpic && epic != NULL) free(epic);
  657.   epic = newpic;  eWIDE = w;  eHIGH = h;
  658.  
  659.   free(cache);
  660.  
  661.   CreateXImage();
  662.   SetCursors(-1);
  663. }
  664.  
  665.  
  666.