home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume5 / dither / tcd.c < prev   
C/C++ Source or Header  |  1986-11-30  |  11KB  |  410 lines

  1. #include <stdio.h>
  2. #include <sys/file.h>
  3. #include <pixrect/pixrect_hs.h>
  4.  
  5. /*
  6.  *    Dither!  Color dither a U.S.C. tape image.
  7.  *
  8.  *    Original Tape code by Brian Kantor.
  9.  *
  10.  *    The dithering is the product of madness and extrapolation
  11.  *    from the concepts employed for black and white dithers,
  12.  *    Jim Hutchison. Presumes 8bit bytes.
  13.  */
  14.  
  15. #define LARGEST        (0xff)            /* 8 bits per color */
  16. #define UNUSED_BITS    0            /* unused bits      */
  17.  
  18. #define R_BITS        3            /* Bits of red               */
  19. #define R_ERR        (8 - R_BITS)        /* Bits of error, from true  */
  20. #define R_SHIFT        (8 - R_BITS)        /* shift to get usefull bits */
  21. #define R_MASK        (LARGEST >> R_BITS)    /* masked off bits           */
  22. #define R_NEXT        (R_MASK - 1)        /* base_color + next = left  */
  23. #define R_TOP        (LARGEST & ~R_MASK)    /* maximal value, red        */
  24. #define R_NVAL        (LARGEST >> R_SHIFT)    /* shades of red + black     */
  25. #define R_MAP        0x07            /* mask to get color table   */
  26.  
  27. #define G_BITS        3            /* Bits of green             */
  28. #define G_ERR        (8 - G_BITS)        /* Bits of error, from true  */
  29. #define G_SHIFT        (8 - G_BITS)        /* shift to get usefull bits */
  30. #define G_MASK        (LARGEST >> G_BITS)    /* masked off bits           */
  31. #define G_NEXT        (G_MASK - 1)        /* base_color + next = left  */
  32. #define G_TOP        (LARGEST & ~G_MASK)    /* maximal value, green      */
  33. #define G_NVAL        (LARGEST >> G_SHIFT)    /* shades of green + black   */
  34. #define G_MAP        (0x07 << 3)        /* mask to get color table   */
  35.  
  36. #define B_BITS        2            /* Bits of blue              */
  37. #define B_ERR        (8 - B_BITS)        /* Bits of error, from true  */
  38. #define B_SHIFT        (8 - B_BITS)        /* shift to get usefull bits */
  39. #define B_MASK        (LARGEST >> B_BITS)    /* masked off bits           */
  40. #define B_NEXT        (B_MASK - 1)        /* base_color + next = left  */
  41. #define B_TOP        (LARGEST & ~B_MASK)    /* maximal value, blue       */
  42. #define B_NVAL        (LARGEST >> B_SHIFT)    /* shades of blue + black    */
  43. #define B_MAP        (0x03 << 6)        /* mask to get color table   */
  44.  
  45. /*
  46.  *    2(4(8)) by 2(4(8)) ordered dither, it all hinges on this dither,
  47.  *    and the color-table.  Note that dithers larger than 4x4
  48.  *    require changes in lower code.
  49.  */
  50.  
  51. #ifdef    LARGE_DITHER
  52.  
  53. #define DSIZE        4    /* must be a power of 2 */
  54. #define DITH_LOG    4    /* log[2](DSIZE*DSIZE) */
  55. #define DMASK        DSIZE-1    /* Dither mask to get position in dither */
  56.  
  57. short dither[DSIZE][DSIZE] = {
  58.     0,    8,    3,    11,
  59.     12,    4,    15,    7,
  60.     2,    10,    1,    9,
  61.     14,    6,    13,    5
  62. };
  63.  
  64. #else    /* LARGE_DITHER */
  65.  
  66. #define DSIZE        2    /* must be a power of 2 */
  67. #define DITH_LOG    2    /* log[2](DSIZE*DSIZE) */
  68. #define DMASK        DSIZE-1    /* Dither mask to get position in dither */
  69.  
  70. short dither[DSIZE][DSIZE] = {
  71.     0,    3,
  72.     2,  1
  73. };
  74.  
  75. #endif    /* LARGE_DITHER */
  76.  
  77. /* Huge dither to use with the 2 bit color, blue
  78. */
  79. #ifdef    BLUE_DITHER
  80.  
  81. #define BDSIZE        8    /* must be a power of 2 */
  82. #define BDITH_LOG    6    /* log[2](BDSIZE*BDSIZE) */
  83. #define BDMASK        BDSIZE-1/* Dither mask to get position in dither */
  84.  
  85. short bdither[BDSIZE][BDSIZE] = {
  86.     0,    32,    12,    44,    3,    35,    15,    47,
  87.     48,    16,    60,    28,    51,    19,    63,    31,
  88.     8,    40,    4,    36,    11,    43,    7,    39,
  89.     56,    24,    52,    20,    59,    27,    55,    23,
  90.     2,    34,    14,    46,    1,    33,    13,    45,
  91.     50,    18,    62,    30,    49,    17,    61,    29,
  92.     10,    42,    6,    38,    9,    41,    5,    37,
  93.     58,    26,    54,    22,    57,    25,    53,    21
  94. };
  95.  
  96. #else    /* BLUE_DITHER */
  97. #define BDITH_LOG    DITH_LOG
  98. #endif    /* BLUE_DITHER */
  99.  
  100. /*
  101.  * Determine if we have more error than we have dither, and
  102.  * give the number of bits we shall have to shift down.
  103.  */
  104. #if (R_ERR - DITH_LOG) > 0
  105. #define R_ISHIFT    (R_ERR - DITH_LOG)
  106. #else
  107. #define R_ISHIFT    (0)
  108. #endif
  109.  
  110. #if (G_ERR - DITH_LOG) > 0
  111. #define G_ISHIFT    (G_ERR - DITH_LOG)
  112. #else
  113. #define G_ISHIFT    (0)
  114. #endif
  115.  
  116. #if (B_ERR - BDITH_LOG) > 0
  117. #define B_ISHIFT    (B_ERR - BDITH_LOG)
  118. #else
  119. #define B_ISHIFT    (0)
  120. #endif
  121.  
  122. /*
  123.  * Image/colormap definitions.
  124.  */
  125. #define    MAPSIZE        256            /* size of pallet     */
  126. #define    COLORS        256            /* number of colors   */
  127. #define IMAGESIZE    512            /* size of tape image */
  128. #define IMAGE_VOL    (IMAGESIZE*IMAGESIZE)    /* volume of image    */
  129.  
  130. #define MAXPATH        1024            /* max length of filename */
  131.  
  132. struct pixrect *display;
  133. struct pixrect *memory_frame;
  134.  
  135. /* for palette (sun) generation */
  136.  
  137. unsigned char red[MAPSIZE], grn[MAPSIZE], blu[MAPSIZE];
  138.  
  139. /* shade tables (for speed) */
  140.  
  141. static unsigned int r_base_right[COLORS];
  142. static unsigned int r_base_left[COLORS];
  143. static unsigned int r_dval[COLORS];
  144.  
  145. static unsigned char g_base_right[COLORS];
  146. static unsigned char g_base_left[COLORS];
  147. static unsigned char g_dval[COLORS];
  148.  
  149. static unsigned char b_base_right[COLORS];
  150. static unsigned char b_base_left[COLORS];
  151. static unsigned char b_dval[COLORS];
  152.  
  153. /* nasty procedures */
  154. int
  155. min(a,b)
  156.     int a,b;
  157. {
  158.     return((a > b)? b : a);
  159. }
  160.  
  161. int
  162. max(a,b)
  163.     int a,b;
  164. {
  165.     return((a > b)? a : b);
  166. }
  167.  
  168. main(argc,argv)
  169.     int argc;
  170.     char **argv;
  171. {
  172.     register unsigned int color, dith_value;
  173.     register unsigned int r_color, g_color, b_color;
  174.     register unsigned char *pr, *pg, *pb;
  175.  
  176. #ifdef    BLUE_DITHER
  177.     unsigned int b_dith_value;
  178. #endif    /* BLUE_DITHER */
  179.  
  180.     int x_imagesize, y_imagesize, image_vol;
  181.  
  182.     int fr, fg, fb;
  183.     int i, plen;
  184.     int x, y;
  185.     char buf[MAXPATH];
  186.     unsigned char *picture, *pict_row;    /* keep row to avoid padding problems */
  187.     int row_bytes;            /* bytes per scan-line */
  188.  
  189.     if (argc < 2) {
  190.     fprintf(stderr, "Usage: %s rgb-imagefile [hsize] [vsize]\n", argv[0]);
  191.     exit(-1);
  192.     }
  193.  
  194.     if (argc > 2) {
  195.     x_imagesize = atoi(argv[2]);
  196.  
  197.     if (argc > 3) {
  198.         y_imagesize = atoi(argv[3]);
  199.     } else {
  200.         y_imagesize = x_imagesize;
  201.     }
  202.  
  203.     image_vol = y_imagesize * x_imagesize;
  204.  
  205.     pr = (unsigned char *) malloc(image_vol * sizeof(unsigned char));
  206.     pg = (unsigned char *) malloc(image_vol * sizeof(unsigned char));
  207.     pb = (unsigned char *) malloc(image_vol * sizeof(unsigned char));
  208.     } else {
  209.     x_imagesize = y_imagesize = IMAGESIZE;
  210.     pr = (unsigned char *) malloc(IMAGE_VOL);
  211.     pg = (unsigned char *) malloc(IMAGE_VOL);
  212.     pb = (unsigned char *) malloc(IMAGE_VOL);
  213.     image_vol = IMAGE_VOL;
  214.     }
  215.  
  216.     printf("high %d wide %d vol %d\n", y_imagesize, x_imagesize, image_vol);
  217.  
  218.     strcpy(buf,argv[1]);
  219.     plen = strlen(buf);
  220.     buf[plen] = 'R';
  221.     fr = open(buf, O_RDONLY, 0444);
  222.     if (fr < 0) {
  223.     perror(buf);
  224.     exit(1);
  225.     }
  226.  
  227.     buf[plen] = 'G';
  228.     fg = open(buf, O_RDONLY, 0444);
  229.     if (fg == 0) {
  230.     perror(buf);
  231.     exit(1);
  232.     }
  233.  
  234.     buf[plen] = 'B';
  235.     fb = open(buf, O_RDONLY, 0444);
  236.     if (fb < 0) {
  237.     perror(buf);
  238.     exit(1);
  239.     }
  240.  
  241.     display = pr_open("/dev/cgone0");
  242.     if (display == NULL) {
  243.     fprintf(stderr,"Color Display not available, sorry\n");
  244.     exit (-1);
  245.     }
  246.  
  247.     puts("Reading RGB files");
  248.  
  249.     if (read(fr, pr, image_vol) <= 0)
  250.         perror("red");
  251.     if (read(fg, pg, image_vol) <= 0)
  252.         perror("grn");
  253.     if (read(fb, pb, image_vol) <= 0)
  254.         perror("blu");
  255.  
  256.     puts("Creating memory pixrect");
  257.  
  258.     /* Get a pointer to a memory pixrect */
  259.     memory_frame = mem_create(x_imagesize, y_imagesize, 8);
  260.  
  261.     /* Get a pointer to the image buffer associated with the memory pixrect */
  262.     pict_row = picture = (unsigned char *) mpr_d(memory_frame)->md_image;
  263.  
  264.     /* Get bytes per scan-line (note that padding exists) */
  265.     row_bytes = mpr_d(memory_frame)->md_linebytes;
  266.  
  267.     puts("Initializing tables");
  268.  
  269.     init_tables();
  270.  
  271.     puts("Processing image");
  272.  
  273.     for (y = 0; y < y_imagesize; y++, picture = pict_row += row_bytes) {
  274.     for (x = 0; x < x_imagesize; x++) {
  275.  
  276.         r_color = *pr++;
  277.         g_color = *pg++;
  278.         b_color = *pb++;
  279.  
  280. #ifdef    BLUE_DITHER
  281.         b_dith_value = bdither[x & BDMASK][y & BDMASK];
  282. #endif    /* BLUE_DITHER */
  283.  
  284.         dith_value = dither[x & DMASK][y & DMASK];
  285.  
  286.         if (r_dval[r_color] > dith_value)
  287.         color = r_base_left[r_color];
  288.         else
  289.         color = r_base_right[r_color];
  290.  
  291.         if (g_dval[g_color] > dith_value)
  292.         color |= g_base_left[g_color];
  293.         else
  294.         color |= g_base_right[g_color];
  295.  
  296. #ifdef    BLUE_DITHER
  297.         if (b_dval[b_color] > b_dith_value)
  298. #else
  299.         if (b_dval[b_color] > dith_value)
  300. #endif    /* BLUE_DITHER */
  301.         color |= b_base_left[b_color];
  302.         else
  303.         color |= b_base_right[b_color];
  304.  
  305.         *picture++ = color;
  306.     }
  307.     }
  308.  
  309.     /*
  310.      *    Generate colormap with (cycle is 8 values):
  311.      *        32  cycles of red
  312.      *        1   cycle  of green
  313.      *        1/2 cycle  of blue
  314.      *    all varying smoothely, note that an improved
  315.      *    map which employs better graduation of color
  316.      *    can be employed, but on our interlaced monitor
  317.      *    this caused an extremely painful flicker.
  318.      */
  319.  
  320.     puts("Building color lookup table");
  321.  
  322.     for (i=0; i < MAPSIZE; i++) {
  323.     red[i] = (i & R_MAP) << R_SHIFT;
  324.     grn[i] = (i & G_MAP) << (G_SHIFT - R_BITS);
  325.     blu[i] = (i & B_MAP) << (B_SHIFT - R_BITS - G_BITS);
  326.     }
  327.  
  328.     pr_putcolormap(display, 0, MAPSIZE, red, grn, blu);
  329.  
  330.     /* copy the complete image to the display, center it also.
  331.     */
  332.  
  333.     puts("Displaying");
  334.  
  335.     pr_rop(display,
  336.        max((display->pr_width - x_imagesize) >> 1, 0),
  337.        max((display->pr_height - y_imagesize) >> 1,0),
  338.        min(display->pr_width, x_imagesize),
  339.        min(display->pr_height, y_imagesize),
  340.        (PIX_SRC|PIX_DONTCLIP), memory_frame, 0, 0);
  341.  
  342.     pr_close(display);
  343.     close(fr);
  344.     close(fg);
  345.     close(fb);
  346. }
  347.  
  348. init_tables()
  349. {
  350.     register unsigned int intensity, i;
  351.     register double true_i;
  352.     register double rfactor, gfactor, bfactor;
  353.  
  354.     rfactor = ((double)R_NVAL) / ((double)R_NVAL+1);
  355.     gfactor = ((double)G_NVAL) / ((double)G_NVAL+1);
  356.     bfactor = ((double)B_NVAL) / ((double)B_NVAL+1);
  357.  
  358.     for (i = 0; i < 256; i++) {
  359.     true_i = (double) i;
  360.  
  361.     /*
  362.      * scale color to fit inside of range
  363.      * calculate right base shade by trimming off error.
  364.      */
  365.     intensity = (unsigned int)(true_i * rfactor);
  366.     r_base_right[i] = intensity & ~R_MASK;
  367.  
  368.     if (r_base_right[i] != R_TOP) {
  369.         r_dval[i] = (intensity & R_MASK) >> R_ISHIFT;
  370.         r_base_left[i] =
  371.         ((intensity + R_NEXT) & R_TOP) >> (UNUSED_BITS+G_BITS+B_BITS);
  372.     } else
  373.         r_dval[i] = 0;
  374.  
  375.     r_base_right[i] >>= (UNUSED_BITS + G_BITS + B_BITS);
  376.  
  377.     /*
  378.      * scale color to fit inside of range
  379.      * calculate right base shade by trimming off error.
  380.      */
  381.     intensity = (unsigned int)(true_i * gfactor);
  382.     g_base_right[i] = intensity & ~G_MASK;
  383.  
  384.     if (g_base_right[i] != G_TOP) {
  385.         g_dval[i] = (intensity & G_MASK) >> G_ISHIFT;
  386.         g_base_left[i] =
  387.         ((intensity + G_NEXT) & G_TOP) >> (UNUSED_BITS + B_BITS);
  388.     } else
  389.         g_dval[i] = 0;
  390.  
  391.     g_base_right[i] >>= (UNUSED_BITS + B_BITS);
  392.  
  393.     /*
  394.      * scale color to fit inside of range
  395.      * calculate right base shade by trimming off error.
  396.      */
  397.     intensity = (unsigned int)(true_i * bfactor);
  398.     b_base_right[i] = intensity & ~B_MASK;
  399.  
  400.     if (b_base_right[i] != B_TOP) {
  401.         b_dval[i] = (intensity & B_MASK) >> B_ISHIFT;
  402.         b_base_left[i] =
  403.         ((intensity + B_NEXT) & B_TOP) >> UNUSED_BITS;
  404.     } else
  405.         b_dval[i] = 0;
  406.  
  407.     b_base_right[i] >>= UNUSED_BITS;
  408.     }
  409. }
  410.