home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / xloadimg.zip / xloadimage.4.1 / halftone.c < prev    next >
C/C++ Source or Header  |  1993-10-21  |  10KB  |  258 lines

  1. /* dither.c:
  2.  *
  3.  * routine for dithering a color image to monochrome based on color
  4.  * intensity.  this is loosely based on an algorithm which barry shein
  5.  * (bzs@std.com) used in his "xf" program.
  6.  *
  7.  * jim frost 07.10.89
  8.  *
  9.  * Copyright 1989, 1990 Jim Frost.
  10.  * See included file "copyright.h" for complete copyright information.
  11.  */
  12.  
  13. #include "copyright.h"
  14. #include "image.h"
  15.  
  16. /* RGB intensity tables.  red is (val * 0.30), green is (val * 0.59), blue
  17.  * is (val * .11), where val is intensity >> 8.  these are used by the
  18.  * colorIntensity() macro in images.h.
  19.  */
  20.  
  21. unsigned short RedIntensity[256]= {
  22.       0,    76,   153,   230,   307,   384,   460,   537,
  23.     614,   691,   768,   844,   921,   998,  1075,  1152,
  24.    1228,  1305,  1382,  1459,  1536,  1612,  1689,  1766,
  25.    1843,  1920,  1996,  2073,  2150,  2227,  2304,  2380,
  26.    2457,  2534,  2611,  2688,  2764,  2841,  2918,  2995,
  27.    3072,  3148,  3225,  3302,  3379,  3456,  3532,  3609,
  28.    3686,  3763,  3840,  3916,  3993,  4070,  4147,  4224,
  29.    4300,  4377,  4454,  4531,  4608,  4684,  4761,  4838,
  30.    4915,  4992,  5068,  5145,  5222,  5299,  5376,  5452,
  31.    5529,  5606,  5683,  5760,  5836,  5913,  5990,  6067,
  32.    6144,  6220,  6297,  6374,  6451,  6528,  6604,  6681,
  33.    6758,  6835,  6912,  6988,  7065,  7142,  7219,  7296,
  34.    7372,  7449,  7526,  7603,  7680,  7756,  7833,  7910,
  35.    7987,  8064,  8140,  8217,  8294,  8371,  8448,  8524,
  36.    8601,  8678,  8755,  8832,  8908,  8985,  9062,  9139,
  37.    9216,  9292,  9369,  9446,  9523,  9600,  9676,  9753,
  38.    9830,  9907,  9984, 10060, 10137, 10214, 10291, 10368,
  39.   10444, 10521, 10598, 10675, 10752, 10828, 10905, 10982,
  40.   11059, 11136, 11212, 11289, 11366, 11443, 11520, 11596,
  41.   11673, 11750, 11827, 11904, 11980, 12057, 12134, 12211,
  42.   12288, 12364, 12441, 12518, 12595, 12672, 12748, 12825,
  43.   12902, 12979, 13056, 13132, 13209, 13286, 13363, 13440,
  44.   13516, 13593, 13670, 13747, 13824, 13900, 13977, 14054,
  45.   14131, 14208, 14284, 14361, 14438, 14515, 14592, 14668,
  46.   14745, 14822, 14899, 14976, 15052, 15129, 15206, 15283,
  47.   15360, 15436, 15513, 15590, 15667, 15744, 15820, 15897,
  48.   15974, 16051, 16128, 16204, 16281, 16358, 16435, 16512,
  49.   16588, 16665, 16742, 16819, 16896, 16972, 17049, 17126,
  50.   17203, 17280, 17356, 17433, 17510, 17587, 17664, 17740,
  51.   17817, 17894, 17971, 18048, 18124, 18201, 18278, 18355,
  52.   18432, 18508, 18585, 18662, 18739, 18816, 18892, 18969,
  53.   19046, 19123, 19200, 19276, 19353, 19430, 19507, 19584
  54. };
  55.  
  56. unsigned short GreenIntensity[256]= {
  57.      0,  151,  302,  453,  604,  755,  906, 1057,
  58.   1208, 1359, 1510, 1661, 1812, 1963, 2114, 2265,
  59.   2416, 2567, 2718, 2869, 3020, 3171, 3322, 3473,
  60.   3624, 3776, 3927, 4078, 4229, 4380, 4531, 4682,
  61.   4833, 4984, 5135, 5286, 5437, 5588, 5739, 5890,
  62.   6041, 6192, 6343, 6494, 6645, 6796, 6947, 7098,
  63.   7249, 7400, 7552, 7703, 7854, 8005, 8156, 8307,
  64.   8458, 8609, 8760, 8911, 9062, 9213, 9364, 9515,
  65.   9666, 9817, 9968,10119,10270,10421,10572,10723,
  66.  10874,11025,11176,11328,11479,11630,11781,11932,
  67.  12083,12234,12385,12536,12687,12838,12989,13140,
  68.  13291,13442,13593,13744,13895,14046,14197,14348,
  69.  14499,14650,14801,14952,15104,15255,15406,15557,
  70.  15708,15859,16010,16161,16312,16463,16614,16765,
  71.  16916,17067,17218,17369,17520,17671,17822,17973,
  72.  18124,18275,18426,18577,18728,18880,19031,19182,
  73.  19333,19484,19635,19786,19937,20088,20239,20390,
  74.  20541,20692,20843,20994,21145,21296,21447,21598,
  75.  21749,21900,22051,22202,22353,22504,22656,22807,
  76.  22958,23109,23260,23411,23562,23713,23864,24015,
  77.  24166,24317,24468,24619,24770,24921,25072,25223,
  78.  25374,25525,25676,25827,25978,26129,26280,26432,
  79.  26583,26734,26885,27036,27187,27338,27489,27640,
  80.  27791,27942,28093,28244,28395,28546,28697,28848,
  81.  28999,29150,29301,29452,29603,29754,29905,30056,
  82.  30208,30359,30510,30661,30812,30963,31114,31265,
  83.  31416,31567,31718,31869,32020,32171,32322,32473,
  84.  32624,32775,32926,33077,33228,33379,33530,33681,
  85.  33832,33984,34135,34286,34437,34588,34739,34890,
  86.  35041,35192,35343,35494,35645,35796,35947,36098,
  87.  36249,36400,36551,36702,36853,37004,37155,37306,
  88.  37457,37608,37760,37911,38062,38213,38364,38515
  89. };
  90.  
  91. unsigned short BlueIntensity[256]= {
  92.      0,   28,   56,   84,  112,  140,  168,  197,
  93.    225,  253,  281,  309,  337,  366,  394,  422,
  94.    450,  478,  506,  535,  563,  591,  619,  647,
  95.    675,  704,  732,  760,  788,  816,  844,  872,
  96.    901,  929,  957,  985, 1013, 1041, 1070, 1098,
  97.   1126, 1154, 1182, 1210, 1239, 1267, 1295, 1323,
  98.   1351, 1379, 1408, 1436, 1464, 1492, 1520, 1548,
  99.   1576, 1605, 1633, 1661, 1689, 1717, 1745, 1774,
  100.   1802, 1830, 1858, 1886, 1914, 1943, 1971, 1999,
  101.   2027, 2055, 2083, 2112, 2140, 2168, 2196, 2224,
  102.   2252, 2280, 2309, 2337, 2365, 2393, 2421, 2449,
  103.   2478, 2506, 2534, 2562, 2590, 2618, 2647, 2675,
  104.   2703, 2731, 2759, 2787, 2816, 2844, 2872, 2900,
  105.   2928, 2956, 2984, 3013, 3041, 3069, 3097, 3125,
  106.   3153, 3182, 3210, 3238, 3266, 3294, 3322, 3351,
  107.   3379, 3407, 3435, 3463, 3491, 3520, 3548, 3576,
  108.   3604, 3632, 3660, 3688, 3717, 3745, 3773, 3801,
  109.   3829, 3857, 3886, 3914, 3942, 3970, 3998, 4026,
  110.   4055, 4083, 4111, 4139, 4167, 4195, 4224, 4252,
  111.   4280, 4308, 4336, 4364, 4392, 4421, 4449, 4477,
  112.   4505, 4533, 4561, 4590, 4618, 4646, 4674, 4702,
  113.   4730, 4759, 4787, 4815, 4843, 4871, 4899, 4928,
  114.   4956, 4984, 5012, 5040, 5068, 5096, 5125, 5153,
  115.   5181, 5209, 5237, 5265, 5294, 5322, 5350, 5378,
  116.   5406, 5434, 5463, 5491, 5519, 5547, 5575, 5603,
  117.   5632, 5660, 5688, 5716, 5744, 5772, 5800, 5829,
  118.   5857, 5885, 5913, 5941, 5969, 5998, 6026, 6054,
  119.   6082, 6110, 6138, 6167, 6195, 6223, 6251, 6279,
  120.   6307, 6336, 6364, 6392, 6420, 6448, 6476, 6504,
  121.   6533, 6561, 6589, 6617, 6645, 6673, 6702, 6730,
  122.   6758, 6786, 6814, 6842, 6871, 6899, 6927, 6955,
  123.   6983, 7011, 7040, 7068, 7096, 7124, 7152, 7180
  124. };
  125.  
  126. /* 4x4 arrays used for dithering, arranged by nybble
  127.  */
  128.  
  129. #define GRAYS    17 /* ((4 * 4) + 1) patterns for a good dither */
  130. #define GRAYSTEP ((unsigned long)(65536 / GRAYS))
  131.  
  132. static byte DitherBits[GRAYS][4] = {
  133.   0xf, 0xf, 0xf, 0xf,
  134.   0xe, 0xf, 0xf, 0xf,
  135.   0xe, 0xf, 0xb, 0xf,
  136.   0xa, 0xf, 0xb, 0xf,
  137.   0xa, 0xf, 0xa, 0xf,
  138.   0xa, 0xd, 0xa, 0xf,
  139.   0xa, 0xd, 0xa, 0x7,
  140.   0xa, 0x5, 0xa, 0x7,
  141.   0xa, 0x5, 0xa, 0x5,
  142.   0x8, 0x5, 0xa, 0x5,
  143.   0x8, 0x5, 0x2, 0x5,
  144.   0x0, 0x5, 0x2, 0x5,
  145.   0x0, 0x5, 0x0, 0x5,
  146.   0x0, 0x4, 0x0, 0x5,
  147.   0x0, 0x4, 0x0, 0x1,
  148.   0x0, 0x0, 0x0, 0x1,
  149.   0x0, 0x0, 0x0, 0x0
  150. };
  151.  
  152. /* simple dithering algorithm, really optimized for the 4x4 array
  153.  */
  154.  
  155. Image *halftone(cimage, verbose)
  156.      Image        *cimage;
  157.      unsigned int  verbose;
  158. { Image         *image;
  159.   unsigned char *sp, *dp, *dp2; /* data pointers */
  160.   unsigned int   dindex;        /* index into dither array */
  161.   unsigned int   spl;           /* source pixel length in bytes */
  162.   unsigned int   dll;           /* destination line length in bytes */
  163.   Pixel          color;         /* pixel color */
  164.   unsigned int  *index;         /* index into dither array for a given pixel */
  165.   unsigned int   a, x, y;       /* random counters */
  166.  
  167.   goodImage(cimage, "dither");
  168.   if (BITMAPP(cimage))
  169.     return(NULL);
  170.  
  171.   /* set up
  172.    */
  173.  
  174.   if (verbose) {
  175.     printf("  Halftoning image...");
  176.     fflush(stdout);
  177.   }
  178.   image= newBitImage(cimage->width * 4, cimage->height * 4);
  179.   if (cimage->title) {
  180.     image->title= (char *)lmalloc(strlen(cimage->title) + 13);
  181.     sprintf(image->title, "%s (halftoned)", cimage->title);
  182.   }
  183.   spl= cimage->pixlen;
  184.   dll= (image->width / 8) + (image->width % 8 ? 1 : 0);
  185.  
  186.   /* if the number of possible pixels isn't very large, build an array
  187.    * which we index by the pixel value to find the dither array index
  188.    * by color brightness.  we do this in advance so we don't have to do
  189.    * it for each pixel.  things will break if a pixel value is greater
  190.    * than (1 << depth), which is bogus anyway.  this calculation is done
  191.    * on a per-pixel basis if the colormap is too big.
  192.    */
  193.  
  194.   if (RGBP(cimage) && (cimage->depth <= 16)) {
  195.     index= (unsigned int *)lmalloc(sizeof(unsigned int) * cimage->rgb.used);
  196.     for (x= 0; x < cimage->rgb.used; x++) {
  197.       *(index + x)=
  198.     ((unsigned long)colorIntensity(*(cimage->rgb.red + x),
  199.                        *(cimage->rgb.green + x),
  200.                        *(cimage->rgb.blue + x))) / GRAYSTEP;
  201.       if (*(index + x) >= GRAYS) /* rounding errors can do this */
  202.     *(index + x)= GRAYS - 1;
  203.     }
  204.   }
  205.   else
  206.     index= NULL;
  207.  
  208.   /* dither each pixel
  209.    */
  210.  
  211.   sp= cimage->data;
  212.   dp= image->data;
  213.   for (y= 0; y < cimage->height; y++) {
  214.     for (x= 0; x < cimage->width; x++) {
  215.       dp2= dp + (x >> 1);
  216.       color= memToVal(sp, spl);
  217.       if (RGBP(cimage)) {
  218.     if (index)
  219.       dindex= *(index + color);
  220.     else {
  221.       dindex= 
  222.         ((unsigned long)colorIntensity(cimage->rgb.red[color],
  223.                        cimage->rgb.green[color],
  224.                        cimage->rgb.blue[color])) / GRAYSTEP;
  225.     }
  226.       }
  227.       else {
  228.     dindex=
  229.       ((unsigned long)colorIntensity((TRUE_RED(color) << 8),
  230.                      (TRUE_GREEN(color) << 8),
  231.                      (TRUE_BLUE(color) << 8))) / GRAYSTEP;
  232.       }
  233.       if (dindex >= GRAYS) /* rounding errors can do this */
  234.     dindex= GRAYS - 1;
  235.  
  236.       /* loop for the four Y bits in the dither pattern, putting all
  237.        * four X bits in at once.  if you think this would be hard to
  238.        * change to be an NxN dithering array, you're right, since we're
  239.        * banking on the fact that we need only shift the mask based on
  240.        * whether x is odd or not.  an 8x8 array wouldn't even need that,
  241.        * but blowing an image up by 64x is probably not a feature.
  242.        */
  243.  
  244.       if (x & 1)
  245.     for (a= 0; a < 4; a++, dp2 += dll)
  246.       *dp2 |= DitherBits[dindex][a];
  247.       else
  248.     for (a= 0; a < 4; a++, dp2 += dll)
  249.       *dp2 |= (DitherBits[dindex][a] << 4);
  250.       sp += spl;
  251.     }
  252.     dp += (dll << 2); /* (dll * 4) but I like shifts */
  253.   }
  254.   if (verbose)
  255.     printf("done\n");
  256.   return(image);
  257. }
  258.