home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / g / gs252src.zip / GS252 / GXCOLOR.C < prev    next >
C/C++ Source or Header  |  1992-07-17  |  8KB  |  291 lines

  1. /* Copyright (C) 1989, 1992 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* gxcolor.c */
  21. /* Private color procedures for Ghostscript library */
  22. #include "gx.h"
  23. #include "gserrors.h"
  24. #include "gxfixed.h"            /* for gxmatrix.h */
  25. #include "gxlum.h"
  26. #include "gxmatrix.h"
  27. #include "gxdevice.h"            /* for gx_color_index */
  28. #include "gzcolor.h"
  29. #include "gscspace.h"
  30. #include "gzht.h"
  31. #include "gzstate.h"
  32.  
  33. /* Imported procedures */
  34. void gx_color_render(P3(gs_color *, gx_device_color *, gs_state *));
  35.  
  36. /* Forward declarations */
  37. void gx_color_from_rgb(P1(gs_color *));
  38.  
  39. /* ------ Color setup routines ------ */
  40.  
  41. /* Set up black for writing into the character cache. */
  42. void
  43. gx_set_black(gs_state *pgs)
  44. {    register gs_color *pcolor = pgs->color;
  45.     pcolor->red = pcolor->green = pcolor->blue = pcolor->luminance = 0;
  46.     pcolor->luminance_set = 1;
  47.     pcolor->is_gray = 1;
  48.     pcolor->space = (byte)gs_color_space_DeviceGray;
  49.     gx_color_render(pcolor, pgs->dev_color, pgs);
  50. }
  51.  
  52. /* Set up a gray color.  This is an internal routine */
  53. /* for use by initialization and gx_remap_color. */
  54. void
  55. gx_set_gray_only(register gs_color *pcolor, color_param gray)
  56. {    pcolor->red = pcolor->green = pcolor->blue =
  57.       pcolor->luminance = gray;
  58.     pcolor->luminance_set = 1;
  59.     pcolor->is_gray = 1;
  60.     pcolor->space = (byte)gs_color_space_DeviceGray;
  61. }
  62.  
  63. /* Set up an RGB color.  This is an internal routine */
  64. /* for use by gx_remap_color. */
  65. void
  66. gx_set_rgb_only(register gs_color *pcolor,
  67.   color_param r, color_param g, color_param b)
  68. {    pcolor->red = r;
  69.     pcolor->green = g;
  70.     pcolor->blue = b;
  71.     gx_color_from_rgb(pcolor);
  72. }
  73.  
  74. /* Set up an RGB color. */
  75. void
  76. gx_color_from_rgb(register gs_color *pcolor)
  77. {    if ( pcolor->red == pcolor->green && pcolor->green == pcolor->blue )
  78.        {    pcolor->luminance = pcolor->red;    /* pick any one */
  79.         pcolor->is_gray = pcolor->luminance_set = 1;
  80.        }
  81.     else
  82.        {    /* Compute luminance later */
  83.         pcolor->is_gray = pcolor->luminance_set = 0;
  84.        }
  85.     pcolor->space = (byte)gs_color_space_DeviceRGB;
  86. }
  87.  
  88. /* Force a parameter into the range [0..1], */
  89. /* and convert to a color_param. */
  90. color_param
  91. gx_color_unit_param(floatp fval)
  92. {    if ( fval <= 0.0 )
  93.         return 0;
  94.     else if ( fval >= 1.0 )
  95.         return max_color_param;
  96.     else
  97.         return (color_param)(fval * max_color_param_float);
  98. }
  99.  
  100. /* Map a color_param through a transfer map. */
  101. color_param
  102. gx_color_param_map(color_param cv, const color_param *values)
  103. {
  104. #define cp_frac_bits (color_param_bits - log2_transfer_map_size)
  105.     int cmi = cv >> cp_frac_bits;
  106.     color_param mv = values[cmi];
  107.     int rem, mdv;
  108.     /* Interpolate between two adjacent values if needed. */
  109.     rem = (cv & ((1 << cp_frac_bits) - 1)) - (cv >> (color_param_bits - cp_frac_bits));
  110.     if ( rem == 0 ) return mv;
  111.     else if ( rem > 0 ) mdv = values[cmi + 1] - mv;
  112.     else mdv = mv - values[cmi - 1];
  113. #if arch_ints_are_short
  114.     /* Only use long multiplication if necessary. */
  115.     if ( mdv > 1 << (16 - cp_frac_bits) )
  116.         return mv + (uint)(((ulong)rem * mdv) >> cp_frac_bits);
  117. #endif
  118.     return mv + ((rem * mdv) >> cp_frac_bits);
  119. #undef cp_frac_bits
  120. }
  121.  
  122. /* Remap the color in the graphics state. */
  123. void gx_render_color(P2(gs_color *, gs_state *));
  124. int
  125. gx_remap_color(gs_state *pgs)
  126. {    const gs_color *pcolor = pgs->color;
  127.     gs_color mcolor;        /* color mapped by transfer procs */
  128. #define mapcp(p,c) gx_map_color_param(pgs, pcolor->c, p)
  129.     switch ( (gs_color_space_type)pcolor->space )
  130.        {
  131.     case gs_color_space_DeviceGray:
  132.         gx_set_gray_only(&mcolor, mapcp(gray, red));    /* any one */
  133.         break;
  134.     case gs_color_space_DeviceRGB:
  135.     case gs_color_space_DeviceCMYK:        /* BOGUS */
  136.         gx_set_rgb_only(&mcolor, mapcp(red, red),
  137.                 mapcp(green, green), mapcp(blue, blue));
  138.         break;
  139.     default:
  140.         return_error(gs_error_undefined);
  141.        }
  142. #undef mapcp
  143.     gx_render_color(&mcolor, pgs);
  144.     return 0;
  145. }
  146. void
  147. gx_render_color(gs_color *pmcolor, gs_state *pgs)
  148. {    gx_color_render(pmcolor, pgs->dev_color, pgs);
  149. }
  150.  
  151. /* ------ Color conversion routines ------ */
  152.  
  153. /* Note: the color model conversion algorithms are taken from */
  154. /* Rogers, Procedural Elements for Computer Graphics, pp. 401-403. */
  155.  
  156. /* Compute (if necessary) and return the luminance of a color. */
  157. color_param
  158. gx_color_luminance(register gs_color *pcolor)
  159. {    if ( !pcolor->luminance_set )
  160.        {    pcolor->luminance =
  161.             (pcolor->red * (unsigned long)lum_red_weight +
  162.             pcolor->green * (unsigned long)lum_green_weight +
  163.             pcolor->blue * (unsigned long)lum_blue_weight +
  164.             (lum_all_weights / 2))
  165.             / lum_all_weights;
  166.         pcolor->luminance_set = 1;
  167.        }
  168.     return pcolor->luminance;
  169. }
  170.  
  171. /* Convert RGB to HSB */
  172. void
  173. gx_color_to_hsb(register const gs_color *pcolor, color_param hsb[3])
  174. {
  175. #define rhue hsb[0]
  176. #define rsat hsb[1]
  177. #define rbri hsb[2]
  178.     if ( pcolor->is_gray )
  179.        {    rhue = 0;    /* arbitrary */
  180.         rsat = 0;
  181.         rbri = pcolor->red;    /* pick any one */
  182.        }
  183.     else
  184.        {    /* Convert rgb to hsb */
  185.         gs_color c;
  186.         color_param V, Temp;
  187.         long diff, H;
  188.         c.red = pcolor->red;
  189.         c.green = pcolor->green;
  190.         c.blue = pcolor->blue;
  191.         V = (c.red > c.green ? c.red : c.green);
  192.         if ( c.blue > V ) V = c.blue;
  193.         Temp = (c.red > c.green ? c.green : c.red);
  194.         if ( c.blue < Temp ) Temp = c.blue;
  195.         diff = V - Temp;
  196.         if ( V == c.red )
  197.             H = (c.green - c.blue) * max_color_param_long / diff;
  198.         else if ( V == c.green )
  199.             H = (c.blue - c.red) * max_color_param_long / diff + 2 * max_color_param_long;
  200.         else /* V == c.blue */
  201.             H = (c.red - c.green) * max_color_param_long / diff + 4 * max_color_param_long;
  202.         if ( H < 0 ) H += 6 * max_color_param_long;
  203.         rhue = H / 6;
  204.         rsat = diff * max_color_param_long / V;
  205.         rbri = V;
  206.        }
  207. #undef rhue
  208. #undef rsat
  209. #undef rbri
  210. }
  211.  
  212. /* Complete color specified by hsb */
  213. void
  214. gx_color_from_hsb(register gs_color *pcolor,
  215.   color_param hue, color_param saturation, color_param brightness)
  216. {    if ( saturation == 0 )
  217.        {    pcolor->red = pcolor->green = pcolor->blue = brightness;
  218.        }
  219.     else
  220.        {    /* Convert hsb to rgb. */
  221.         /* We rely on the fact that the product of two */
  222.         /* color_params fits into an unsigned long. */
  223.         ulong V = brightness;    /* force arithmetic to long */
  224.         color_param S = saturation;
  225. #define mcp max_color_param
  226. #define mcpl max_color_param_long
  227. #define mcp6 (mcp / 6 + 1)
  228.         ulong F = (hue % mcp6) * 6;    /* ditto */
  229.         int I = hue / mcp6;
  230.         color_param M = V * (mcpl - S) / mcpl;
  231.         color_param N = V * (mcpl - S * F / mcpl) / mcpl;
  232.         color_param K = V * (mcpl - S * (mcpl - F) / mcpl) / mcpl;
  233. #undef mcp6
  234. #undef mcpl
  235. #undef mcp
  236.         color_param R, G, B;
  237.         switch ( I )
  238.            {
  239.         default: R = V; G = K; B = M; break;
  240.         case 1: R = N; G = V; B = M; break;
  241.         case 2: R = M; G = V; B = K; break;
  242.         case 3: R = M; G = N; B = V; break;
  243.         case 4: R = K; G = M; B = V; break;
  244.         case 5: R = V; G = M; B = N; break;
  245.            }
  246.         pcolor->red = R;
  247.         pcolor->green = G;
  248.         pcolor->blue = B;
  249.        }
  250.     gx_color_from_rgb(pcolor);    /* compute luminance */
  251. }
  252.  
  253. /* ------ Internal routines ------ */
  254.  
  255. /* Heapsort (algorithm 5.2.3H, Knuth vol. 2, p. 146), */
  256. /* modified for 0-origin indexing. */
  257. void
  258. gx_sort_ht_order(ht_bit *recs, uint N)
  259. {    uint l = N >> 1;
  260.     uint r = N - 1;
  261.     uint j;
  262.     ht_bit R;
  263.     if ( N <= 1 ) return;
  264. #define key(m) recs[m].mask
  265. #define K R.mask
  266.     while ( 1 )
  267.        {    if ( l > 0 )
  268.             R = recs[--l];
  269.         else
  270.            {    R = recs[r];
  271.             recs[r] = recs[0];
  272.             if ( --r == 0 )
  273.                {    recs[0] = R;
  274.                 break;
  275.                }
  276.            }
  277.         j = l;
  278.         while ( 1 )
  279.            {    uint i = j;
  280.             j = j + j + 1;
  281.             if ( j < r )
  282.                 if ( key(j) < key(j + 1) ) j++;
  283.             if ( j > r || K >= key(j) )
  284.                {    recs[i] = R;
  285.                 break;    /* to outer loop */
  286.                }
  287.             recs[i] = recs[j];
  288.            }
  289.        }
  290. }
  291.