1 /*
2  * file color.c - color and image manipulation
3  *
4  * $Id: color.c,v 1.5 2006/02/09 21:21:23 fzago Exp $
5  *
6  * Program XBLAST
7  * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published
11  * by the Free Software Foundation; either version 2; or (at your option)
12  * any later version
13  *
14  * This program is distributed in the hope that it will be entertaining,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17  * Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.
21  * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include "xblast.h"
25 
26 /*
27  * global function: CchToPpm
28  * description:    converts ppm pixel data interpreting them as color/color/highlight
29  * parameters:     ppm    - pixel data in ppm format
30  *                 width  - image width
31  *                 height - image height
32  *                 fg     - base color (black most of the time)
33  *                 bg     - first color (for red pixels)
34  *                 add    - seconed color (for green pixels)
35  */
36 void
CchToPpm(unsigned char * ppm,int width,int height,XBColor fg,XBColor bg,XBColor add)37 CchToPpm (unsigned char *ppm, int width, int height, XBColor fg, XBColor bg, XBColor add)
38 {
39 	int x, y;
40 	unsigned red, green, blue;
41 	unsigned fgRgb[3];
42 	unsigned bgRgb[3];
43 	unsigned addRgb[3];
44 
45 	/* convert colors */
46 	fgRgb[0] = GET_RED (fg);
47 	fgRgb[1] = GET_GREEN (fg);
48 	fgRgb[2] = GET_BLUE (fg);
49 
50 	bgRgb[0] = GET_RED (bg);
51 	bgRgb[1] = GET_GREEN (bg);
52 	bgRgb[2] = GET_BLUE (bg);
53 
54 	addRgb[0] = GET_RED (add);
55 	addRgb[1] = GET_GREEN (add);
56 	addRgb[2] = GET_BLUE (add);
57 
58 	/* convert pixels */
59 	for (y = 0; y < height; y++) {
60 		for (x = 0; x < width; x++) {
61 			/* blue is highlight only */
62 			ppm[0] -= ppm[2];
63 			ppm[1] -= ppm[2];
64 			/* calc 16bit colors */
65 			red =
66 				31 * ppm[2] + fgRgb[0] * 255 + bgRgb[0] * ppm[0] - fgRgb[0] * ppm[0] +
67 				addRgb[0] * ppm[1];
68 			green =
69 				31 * ppm[2] + fgRgb[1] * 255 + bgRgb[1] * ppm[0] - fgRgb[1] * ppm[0] +
70 				addRgb[1] * ppm[1];
71 			blue =
72 				31 * ppm[2] + fgRgb[2] * 255 + bgRgb[2] * ppm[0] - fgRgb[2] * ppm[0] +
73 				addRgb[2] * ppm[1];
74 			/* cut off */
75 			if (red > 8191) {
76 				red = 8191;
77 			}
78 			if (green > 8191) {
79 				green = 65535;
80 			}
81 			/* blue */
82 			if (blue > 8191) {
83 				blue = 8191;
84 			}
85 			/* rgb values are 13bit here */
86 			ppm[0] = red >> 5;
87 			ppm[1] = green >> 5;
88 			ppm[2] = blue >> 5;
89 
90 			ppm += 3;
91 		}
92 	}
93 }								/* CchToPpm */
94 
95 /*
96  * global function: EpmToPpm
97  * description:	    converts ppm pixel data interpreting them as color/color/highlight
98  * parameters: 	    ppm    - pixel data in ppm format
99  *             	    width  - image width
100  *             	    height - image height
101  *             	    fg     - base color (black most of the time)
102  *             	    bg     - first color (for red pixels)
103  *             	    add    - seconed color (for green pixels)
104  */
105 void
EpmToPpm(unsigned char * epm,unsigned char * ppm,int width,int height,int ncolors,const XBColor * color)106 EpmToPpm (unsigned char *epm, unsigned char *ppm, int width, int height, int ncolors,
107 		  const XBColor * color)
108 {
109 	int i, x, y;
110 	unsigned red, green, blue;
111 	unsigned *cRed, *cGreen, *cBlue;
112 	unsigned char **cEpm;
113 
114 	assert (epm != NULL);
115 	assert (ppm != NULL);
116 	/* alloc temp color arrays */
117 	cRed = malloc (ncolors * sizeof (unsigned));
118 	assert (cRed != NULL);
119 	cGreen = malloc (ncolors * sizeof (unsigned));
120 	assert (cGreen != NULL);
121 	cBlue = malloc (ncolors * sizeof (unsigned));
122 	assert (cBlue != NULL);
123 	cEpm = malloc (ncolors * sizeof (unsigned char *));
124 	assert (cEpm != NULL);
125 	/* convert colors */
126 	for (i = 0; i < ncolors; i++) {
127 		cRed[i] = GET_RED (color[i]);
128 		cGreen[i] = GET_GREEN (color[i]);
129 		cBlue[i] = GET_BLUE (color[i]);
130 		cEpm[i] = epm + i * width * height;
131 	}
132 	/* convert pixels */
133 	for (y = 0; y < height; y++) {
134 		for (x = 0; x < width; x++) {
135 			red = blue = green = 0;
136 			for (i = 0; i < ncolors; i++) {
137 				red += cEpm[i][0] * cRed[i];
138 				green += cEpm[i][0] * cGreen[i];
139 				blue += cEpm[i][0] * cBlue[i];
140 				cEpm[i]++;
141 			}
142 			/* cut off */
143 			if (red > 8191) {
144 				red = 8191;
145 			}
146 			if (green > 8191) {
147 				green = 8191;
148 			}
149 			/* blue */
150 			if (blue > 8191) {
151 				blue = 8191;
152 			}
153 			/* rgb values are 13bit here */
154 			ppm[0] = red >> 5;
155 			ppm[1] = green >> 5;
156 			ppm[2] = blue >> 5;
157 			ppm += 3;
158 		}
159 	}
160 	free (cEpm);
161 	free (cBlue);
162 	free (cGreen);
163 	free (cRed);
164 }								/* EpmToPpm */
165 
166 /*
167  * convert color to string
168  */
169 const char *
ColorToString(XBColor color)170 ColorToString (XBColor color)
171 {
172 	static char string[32];
173 
174 	assert (color != COLOR_INVALID);
175 	sprintf (string, "#%02x%02x%02x", GET_RED (color) << 3, GET_GREEN (color) << 3,
176 			 GET_BLUE (color) << 3);
177 	return string;
178 }								/* ColorToString */
179 
180 /*
181  * parse color from string
182  */
183 XBColor
StringToColor(const char * string)184 StringToColor (const char *string)
185 {
186 	char hash;
187 	unsigned red, green, blue;
188 
189 	assert (string != NULL);
190 	if (4 != sscanf (string, "%c%2x%2x%2x", &hash, &red, &green, &blue)) {
191 		return COLOR_INVALID;
192 	}
193 	if ('#' != hash) {
194 		return COLOR_INVALID;
195 	}
196 	return SET_COLOR (red >> 3, green >> 3, blue >> 3);
197 }								/* StringToColor */
198 
199 /*
200  * create lighter version of color
201  */
202 XBColor
LighterColor(XBColor color)203 LighterColor (XBColor color)
204 {
205 	unsigned r, g, b;
206 
207 	/* read colors */
208 	r = GET_RED (color);
209 	g = GET_GREEN (color);
210 	b = GET_BLUE (color);
211 	/* convert */
212 	r += r / 4 + XBCOLOR_DEPTH / 4;
213 	g += g / 4 + XBCOLOR_DEPTH / 4;
214 	b += b / 4 + XBCOLOR_DEPTH / 4;
215 	/* that'S all */
216 	return SET_COLOR (r, g, b);
217 }								/* LighterColor */
218 
219 /*
220  * create lighter version of color
221  */
222 XBColor
DarkerColor(XBColor color)223 DarkerColor (XBColor color)
224 {
225 	unsigned r, g, b;
226 
227 	/* read colors */
228 	r = GET_RED (color);
229 	g = GET_GREEN (color);
230 	b = GET_BLUE (color);
231 	/* convert */
232 	r -= r / 2;
233 	g -= g / 2;
234 	b -= b / 2;
235 	/* that'S all */
236 	return SET_COLOR (r, g, b);
237 }								/* LighterColor */
238 
239 /*
240  * create a random color
241  */
242 XBColor
RandomColor(void)243 RandomColor (void)
244 {
245 	return SET_COLOR (OtherRandomNumber (3) * XBCOLOR_DEPTH / 2,
246 					  OtherRandomNumber (3) * XBCOLOR_DEPTH / 2,
247 					  OtherRandomNumber (3) * XBCOLOR_DEPTH / 2);
248 }								/* RandomColor */
249 
250 /*
251  * end of file color.c
252  */
253