home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1787 / floydstein.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  4.9 KB  |  190 lines

  1. /*
  2.  * floydstein.c -- perform Floyd-Steinberg dithering on an in-memory image.
  3.  *
  4.  * This is designed around the NeWS colour map and is for colour mapped
  5.  * images.  Beware.
  6.  *
  7.  * This code is based on ppmquant from Jef Poskanzer's PBM+ package which is
  8.  *
  9.  * Copyright (C) 1989 by Jef Poskanzer.
  10.  *
  11.  * Permission to use, copy, modify, and distribute this software and its
  12.  * documentation for any purpose and without fee is hereby granted, provided
  13.  * that the above copyright notice appear in all copies and that both that
  14.  * copyright notice and this permission notice appear in supporting
  15.  * documentation.  This software is provided "as is" without express or
  16.  * implied warranty.
  17. */
  18.  
  19. #include <stdio.h>
  20. #include <malloc.h>
  21.  
  22. #include "mem_image.h"
  23. #include "newsmap.h"
  24.  
  25. long* long_alloc();
  26.  
  27. unsigned char red[256], green[256], blue[256];
  28. unsigned short news_red[256];
  29. unsigned short news_green[256];
  30. unsigned short news_blue[256];
  31. long *thisrerr, *nextrerr, *thisgerr, *nextgerr, *thisberr, *nextberr;
  32. int fs_direction;
  33.  
  34. void init_floydstein(img)
  35. struct mem_image*    img;
  36. {
  37.     register int col;
  38. #define FS_SCALE 1024
  39.     int i;
  40.  
  41.     /* Build a local colour map for convenience */
  42.     for (i = 0; i < img->maplen; i++) {
  43.         red[i] = img->colourmap[i] & 255;
  44.         green[i] = (img->colourmap[i] >> 8) & 255;
  45.         blue[i] = (img->colourmap[i] >> 16) & 255;
  46.     }
  47.  
  48.     for (i = 0; i < 256; i++)
  49.         getmcolor(i, news_red + i, news_green + i, news_blue + i);
  50.  
  51.     /* Initialize Floyd-Steinberg error vectors. */
  52.     thisrerr = long_alloc(img->width + 2);
  53.     nextrerr = long_alloc(img->width + 2);
  54.     thisgerr = long_alloc(img->width + 2);
  55.     nextgerr = long_alloc(img->width + 2);
  56.     thisberr = long_alloc(img->width + 2);
  57.     nextberr = long_alloc(img->width + 2);
  58.  
  59.     srand((int)time(0));
  60.  
  61.     for (col = 0; col < img->width + 2; col++) {
  62.         thisrerr[col] = rand() % (FS_SCALE * 2) - FS_SCALE;
  63.         thisgerr[col] = rand() % (FS_SCALE * 2) - FS_SCALE;
  64.         thisberr[col] = rand() % (FS_SCALE * 2) - FS_SCALE;
  65.         /* (random errors in [-1 .. 1]) */
  66.     }
  67.     fs_direction = 1;
  68. }
  69.  
  70. void floydstein(img, row)
  71. struct mem_image*    img;
  72. int                    row;
  73. {
  74.     register unsigned char* pP;
  75.     int rows, cols;
  76.     register int col, limitcol;
  77.     long* temperr;
  78.     register long sr, sg, sb;
  79.     int r, g, b;
  80. #define FS_SCALE 1024
  81.     int err;
  82.     int i;
  83.  
  84.     for (col = 0; col < img->width + 2; col++)
  85.         nextrerr[col] = nextgerr[col] = nextberr[col] = 0;
  86.  
  87.     if (fs_direction ) {
  88.         col = 0;
  89.         limitcol = img->width;
  90.         pP = img->data + row * img->width;
  91.     }
  92.     else {
  93.         col = img->width - 1;
  94.         limitcol = -1;
  95.         pP = img->data + row * img->width + img->width - 1;
  96.     }
  97.  
  98.     do {
  99.         /* Use Floyd-Steinberg errors to adjust actual color. */
  100.         sr = red[*pP] * FS_SCALE + thisrerr[col + 1];
  101.         sg = green[*pP] * FS_SCALE + thisgerr[col + 1];
  102.         sb = blue[*pP] * FS_SCALE + thisberr[col + 1];
  103.         r = sr / FS_SCALE; if (r < 0) r = 0; else if (r > 255) r = 255;
  104.         g = sg / FS_SCALE; if (g < 0) g = 0; else if (g > 255) g = 255;
  105.         b = sb / FS_SCALE; if (b < 0) b = 0; else if (b > 255) b = 255;
  106.         /* just for fun, replace the previous 3 lines with these */
  107.         /*r = (sr / FS_SCALE) & 255;
  108.         g = (sg / FS_SCALE) & 255;
  109.         b = (sb / FS_SCALE) & 255;*/
  110.         *pP = rgb2newsmap(r, g, b);
  111.  
  112.         if (fs_direction) {
  113.             err = sr - news_red[*pP] * FS_SCALE;
  114.             thisrerr[col + 2] += ( err * 7 ) / 16;
  115.             nextrerr[col    ] += ( err * 3 ) / 16;
  116.             nextrerr[col + 1] += ( err * 5 ) / 16;
  117.             nextrerr[col + 2] += ( err     ) / 16;
  118.             err = sg - news_green[*pP] * FS_SCALE;
  119.             thisgerr[col + 2] += ( err * 7 ) / 16;
  120.             nextgerr[col    ] += ( err * 3 ) / 16;
  121.             nextgerr[col + 1] += ( err * 5 ) / 16;
  122.             nextgerr[col + 2] += ( err     ) / 16;
  123.             err = sb - news_blue[*pP] * FS_SCALE;
  124.             thisberr[col + 2] += ( err * 7 ) / 16;
  125.             nextberr[col    ] += ( err * 3 ) / 16;
  126.             nextberr[col + 1] += ( err * 5 ) / 16;
  127.             nextberr[col + 2] += ( err     ) / 16;
  128.         }
  129.         else {
  130.             err = sr - news_red[*pP] * FS_SCALE;
  131.             thisrerr[col    ] += ( err * 7 ) / 16;
  132.             nextrerr[col + 2] += ( err * 3 ) / 16;
  133.             nextrerr[col + 1] += ( err * 5 ) / 16;
  134.             nextrerr[col    ] += ( err     ) / 16;
  135.             err = sg - news_green[*pP] * FS_SCALE;
  136.             thisgerr[col    ] += ( err * 7 ) / 16;
  137.             nextgerr[col + 2] += ( err * 3 ) / 16;
  138.             nextgerr[col + 1] += ( err * 5 ) / 16;
  139.             nextgerr[col    ] += ( err     ) / 16;
  140.             err = sb - news_blue[*pP] * FS_SCALE;
  141.             thisberr[col    ] += ( err * 7 ) / 16;
  142.             nextberr[col + 2] += ( err * 3 ) / 16;
  143.             nextberr[col + 1] += ( err * 5 ) / 16;
  144.             nextberr[col    ] += ( err     ) / 16;
  145.         }
  146.         if (fs_direction) {
  147.             col++;
  148.             pP++;
  149.         }
  150.         else {
  151.             col--;
  152.             pP--;
  153.         }
  154.     } while (col != limitcol);
  155.  
  156.     temperr = thisrerr;
  157.     thisrerr = nextrerr;
  158.     nextrerr = temperr;
  159.     temperr = thisgerr;
  160.     thisgerr = nextgerr;
  161.     nextgerr = temperr;
  162.     temperr = thisberr;
  163.     thisberr = nextberr;
  164.     nextberr = temperr;
  165.     fs_direction = !fs_direction;
  166. }
  167.  
  168. clean_floyd()
  169. {
  170.     free(thisrerr);
  171.     free(nextrerr);
  172.     free(thisgerr);
  173.     free(nextgerr);
  174.     free(thisberr);
  175.     free(nextberr);
  176. }
  177.  
  178. long* long_alloc(n)
  179. int    n;
  180. {
  181.     long*    l;
  182.  
  183.     l = (long*)malloc(n * sizeof(long));
  184.  
  185.     if (l == NULL)
  186.         no_mem();
  187.     
  188.     return(l);
  189. }
  190.