home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / Assembler / dse-src3.dms / in.adf / Source / Vectors / Dithering / DitherSrc.lha / Dither.C
Encoding:
C/C++ Source or Header  |  1993-01-06  |  3.6 KB  |  151 lines

  1. /*
  2.  * dither -- use a reduced set of grey values to represent an image
  3.  *
  4.  * Copyright (C) 1988 by Dale Schumacher.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose and without fee is hereby granted, provided
  8.  * that the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation.  This software is provided "as is" without express or
  11.  * implied warranty.
  12.  *
  13.  *
  14.  * Notes:
  15.  *
  16.  * [1] Floyd-Steinberg dither:
  17.  *  I should point out that the actual fractions we used were, assuming
  18.  *  you are at X, moving left to right:
  19.  *
  20.  *            X     7/16
  21.  *         3/16   5/16  1/16    
  22.  *
  23.  *  Note that the error goes to four neighbors, not three.  I think this
  24.  *  will probably do better (at least for black and white) than the
  25.  *  3/8-3/8-1/4 distribution, at the cost of greater processing.  I have
  26.  *  seen the 3/8-3/8-1/4 distribution described as "our" algorithm before,
  27.  *  but I have no idea who the credit really belongs to.
  28.  
  29.  *  Also, I should add that if you do zig-zag scanning (see my immediately
  30.  *  previous message), it is sufficient (but not quite as good) to send
  31.  *  half the error one pixel ahead (e.g. to the right on lines you scan
  32.  *  left to right), and half one pixel straight down.  Again, this is for
  33.  *  black and white;  I've not tried it with color.
  34.  *  -- 
  35.  *                        Lou Steinberg
  36.  */
  37.  
  38. static char    _Program[] = "dither";
  39. static char    _Version[] = "1.3";
  40. static char    _Copyright[] = "Copyright 1988 by Dale Schumacher";
  41.  
  42. #include <stdio.h>
  43. #include <ctype.h>
  44. #include "pxm.h"
  45.  
  46. #define    DEBUG(x)    if(0)/* x */
  47.  
  48. #define    range    255        /* maximum pixel output value */
  49.  
  50. int    levels = 2;        /* number of output levels */
  51.  
  52. banner()
  53.     {
  54.     printf("%s v%s -- %s\n", _Program, _Version, _Copyright);
  55.     }
  56.  
  57. usage()
  58.     {
  59.     fprintf(stderr,
  60.         "usage: %s [-n levels] inpxm outpxm\n",
  61.         _Program);
  62.     exit(1);
  63.     }
  64.  
  65. main(argc, argv)
  66.     int argc;
  67.     char *argv[];
  68.     {
  69.     register PX_DEF *ipx, *opx;
  70.     FILE *f;
  71.     register int c;
  72.     register char *p;
  73.     extern int optind;
  74.     extern char *optarg;
  75.  
  76.     while((c = getopt(argc, argv, "n:V")) != EOF)
  77.         {
  78.         switch(c)
  79.             {
  80.             case 'n':
  81.                 levels = atoi(optarg);
  82.                 break;
  83.             case 'V':
  84.                 banner();
  85.                 exit(0);
  86.             case '?':
  87.             default:
  88.                 usage();
  89.             }
  90.         }
  91.     if((argc - optind) < 2)
  92.         usage();
  93.     else
  94.         {
  95.         ipx = px_ropen(argv[optind++]);
  96.         opx = px_wopen(argv[optind++],
  97.             (PXT_PIX | PXT_BIN),
  98.             ipx->px_width, ipx->px_height, 8, NULL);
  99.         dither(ipx, opx);
  100.         px_close(ipx);
  101.         px_close(opx);
  102.         }
  103.     exit(0);
  104.     }
  105.  
  106. dither(ipx, opx)
  107.     PX_DEF *ipx, *opx;
  108.     {
  109.     unsigned int xsize, ysize;
  110.     unsigned int y, x;
  111.     register int xslop, *yslop, dslop;
  112.     register int i, j, k, t, q;
  113.     register PX_BYTE *ibuf, *obuf;
  114.  
  115.     xsize = ipx->px_width;
  116.     ysize = ipx->px_height;
  117.     ibuf = px_rowalloc(xsize, ipx->px_psize);
  118.     obuf = px_rowalloc(xsize, opx->px_psize);
  119.     yslop = (int *) px_alloc(xsize * sizeof(int));
  120.  
  121.     t = ((range + 1) * 2) / levels;        /* threshold factor */
  122.     q = range / (levels - 1);        /* quantization factor */
  123.     j = (9 * range) / 32;
  124.     for(x=0; x<xsize; ++x)
  125.         yslop[x] = j;
  126.  
  127.     for(y=0; y<ysize; ++y)
  128.         {
  129.         xslop = (7 * range) / 32;
  130.         dslop = range / 32;
  131.         px_rrow(ipx, ibuf);
  132.         for(x=0; x<xsize; ++x)
  133.             {
  134.             i = px_rgrey(ipx, ibuf, x);
  135.             i += xslop + yslop[x];
  136.             j = (i / t) * q;
  137.             if(j > range)        /* quick hack to fix overflow */
  138.                 j = range;    /* which shouldn't happen :-) */
  139.             px_wgrey(opx, obuf, x, j);
  140.             i = i - j;
  141.             k = (i >> 4);        /* (i / 16) */
  142.             xslop = 7 * k;
  143.             yslop[x] = (5 * k) + dslop;
  144.             if(x > 0)
  145.                 yslop[x-1] += 3 * k;
  146.             dslop = i - (15 * k);
  147.             }
  148.         px_wrow(opx, obuf);
  149.         }
  150.     }
  151.