1 /* Copyright (C) 2001-2012 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file LICENSE in this distribution.
10
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13 CA 94903, U.S.A., +1(415)492-9861, for further information.
14 */
15
16 /* Support routines for PC color mapping */
17 #include "gx.h"
18 #include "gsmatrix.h" /* for gxdevice.h */
19 #include "gxdevice.h"
20 #include "gdevpccm.h" /* interface */
21
22 /* Color mapping routines for EGA/VGA-style color. */
23
24 /* ------ EGA/VGA (4-bit) color mapping ------ */
25
26 /*
27 * Colors are 4 bits: 8=intensity (always set except black), 4=R, 2=G, 1=B.
28 * Note: We only use eight colors. The halftoning logic requires that we
29 * have the same number for shades for each component.
30 */
31 gx_color_index
pc_4bit_map_rgb_color(gx_device * dev,const gx_color_value cv[])32 pc_4bit_map_rgb_color(gx_device * dev, const gx_color_value cv[])
33 {
34 gx_color_index r, g, color;
35
36 r = (cv[0] > (gx_max_color_value/2));
37 g = (cv[1] > (gx_max_color_value/2));
38 color = (cv[2] > (gx_max_color_value/2));
39 color += (r << 2) + (g << 1);
40 if (color > 0) /* If the color is not black */
41 color += 8; /* Turn on intensity bit */
42 return color;
43 }
44
45 int
pc_4bit_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])46 pc_4bit_map_color_rgb(gx_device * dev, gx_color_index color,
47 gx_color_value prgb[3])
48 {
49 #define icolor (int)color
50 prgb[0] = (icolor & 4 ? gx_max_color_value : 0);
51 prgb[1] = (icolor & 2 ? gx_max_color_value : 0);
52 prgb[2] = (icolor & 1 ? gx_max_color_value : 0);
53 return 0;
54 #undef icolor
55 }
56
57 /* ------ SVGA 8-bit color mapping ------ */
58 /*
59 * For 8-bit color, we use a 6x6x6 "cube". This only provides 216
60 * different colors. The halftoning logic assumes that we have the same
61 * number of shades of each color. Thus asymetric cubes like 8x8x4 or
62 * 7x7x5 do not work properly.
63 */
64
65 gx_color_index
pc_8bit_map_rgb_color(gx_device * dev,const gx_color_value cv[])66 pc_8bit_map_rgb_color(gx_device * dev, const gx_color_value cv[])
67 {
68 gx_color_value r, g, b;
69 uint rv, gv;
70 r = cv[0]; g = cv[1]; b = cv[2];
71 rv = r / (gx_max_color_value / 6 + 1);
72 gv = g / (gx_max_color_value / 6 + 1);
73
74 return (gx_color_index)
75 (rv * 6 + gv) * 6 + b / (gx_max_color_value / 6 + 1);
76 }
77 int
pc_8bit_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])78 pc_8bit_map_color_rgb(gx_device * dev, gx_color_index color,
79 gx_color_value prgb[3])
80 {
81 static const gx_color_value ramp6[6] =
82 {0,
83 gx_max_color_value / 5,
84 2 * gx_max_color_value / 5,
85 3 * gx_max_color_value / 5,
86 gx_max_color_value - (gx_max_color_value / 5),
87 gx_max_color_value
88 };
89
90 #define icolor (uint)color
91 if (icolor >= 216) {
92 prgb[0] = prgb[1] = prgb[2] = 0;
93 } else {
94 prgb[0] = ramp6[icolor / 36];
95 prgb[1] = ramp6[(icolor / 6) % 6];
96 prgb[2] = ramp6[icolor % 6];
97 }
98 #undef icolor
99 return 0;
100 }
101
102 /* Write a palette on a file. */
103 int
pc_write_palette(gx_device * dev,uint max_index,FILE * file)104 pc_write_palette(gx_device * dev, uint max_index, FILE * file)
105 {
106 uint i, c;
107 gx_color_value rgb[3];
108
109 for (i = 0; i < max_index; i++) {
110 (*dev_proc(dev, map_color_rgb)) (dev, (gx_color_index) i, rgb);
111 for (c = 0; c < 3; c++) {
112 byte b = rgb[c] >> (gx_color_value_bits - 8);
113
114 fputc(b, file);
115 }
116 }
117 return 0;
118 }
119