1 /*
2 * Example program for the Allegro library, by Shawn Hargreaves.
3 *
4 * Modified by Andrei Ellman to include color-bars.
5 *
6 * This program shows how to convert colors between the different
7 * color-space representations. The central area of the screen
8 * will display the current color. On the top left corner of the
9 * screen, three sliders allow you to modify the red, green and
10 * blue value of the color. On the bottom right corner of the
11 * screen, three sliders allow you to modify the hue, saturation
12 * and value of the color. The color bars beneath the sliders
13 * show what the resulting color will look like when the slider
14 * is dragged to that position.
15 *
16 * Additionally this example also shows how to "inherit" the
17 * behaviour of a GUI object and extend it, here used to create
18 * the sliders.
19 */
20
21
22 #include <allegro.h>
23
24
25 #define DIALOG_NUM_SLIDERS 6
26 #define DIALOG_FIRST_COLOR_BAR 12
27 #define DIALOG_COLOR_BOX 18
28
29 /* slider types (R, G, B, and H, S, V) */
30 #define S_R 0
31 #define S_G 1
32 #define S_B 2
33 #define S_H 3
34 #define S_S 4
35 #define S_V 5
36
37
38
39 /* the current color values */
40 int colors[DIALOG_NUM_SLIDERS] =
41 {
42 255, /* red */
43 255, /* green */
44 255, /* blue */
45 0, /* hue */
46 0, /* saturation */
47 255, /* value */
48 };
49
50
51 /* the bitmaps containing the color-bars */
52 BITMAP *color_bar_bitmap[DIALOG_NUM_SLIDERS];
53
54 #if 0
55 /* RGB -> color mapping table. Not needed, but speeds things up in 8-bit mode */
56 RGB_MAP rgb_table;
57 #endif
58
59 int my_slider_proc(int msg, DIALOG *d, int c);
60 int update_color_value(void *dp3, int val);
61
62
63
64 DIALOG the_dlg[] =
65 {
66 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */
67 { my_slider_proc, 32, 16, 256, 16, 0, 255, 0, 0, 255, 0, NULL, (void *)update_color_value, &colors[S_R] },
68 { my_slider_proc, 32, 64, 256, 16, 0, 255, 0, 0, 255, 0, NULL, (void *)update_color_value, &colors[S_G] },
69 { my_slider_proc, 32, 112, 256, 16, 0, 255, 0, 0, 255, 0, NULL, (void *)update_color_value, &colors[S_B] },
70 { my_slider_proc, 352, 336, 256, 16, 0, 255, 0, 0, 255, 0, NULL, (void *)update_color_value, &colors[S_H] },
71 { my_slider_proc, 352, 384, 256, 16, 0, 255, 0, 0, 255, 0, NULL, (void *)update_color_value, &colors[S_S] },
72 { my_slider_proc, 352, 432, 256, 16, 0, 255, 0, 0, 255, 0, NULL, (void *)update_color_value, &colors[S_V] },
73 { d_text_proc, 308, 22, 0, 0, 0, 255, 0, 0, 0, 0, "R", NULL, NULL },
74 { d_text_proc, 308, 70, 0, 0, 0, 255, 0, 0, 0, 0, "G", NULL, NULL },
75 { d_text_proc, 308, 118, 0, 0, 0, 255, 0, 0, 0, 0, "B", NULL, NULL },
76 { d_text_proc, 326, 342, 0, 0, 0, 255, 0, 0, 0, 0, "H", NULL, NULL },
77 { d_text_proc, 326, 390, 0, 0, 0, 255, 0, 0, 0, 0, "S", NULL, NULL },
78 { d_text_proc, 326, 438, 0, 0, 0, 255, 0, 0, 0, 0, "V", NULL, NULL },
79 { d_bitmap_proc, 32, 32, 256, 16, 0, 255, 0, 0, 0, 0, NULL, NULL, NULL },
80 { d_bitmap_proc, 32, 80, 256, 16, 0, 255, 0, 0, 0, 0, NULL, NULL, NULL },
81 { d_bitmap_proc, 32, 128, 256, 16, 0, 255, 0, 0, 0, 0, NULL, NULL, NULL },
82 { d_bitmap_proc, 352, 352, 256, 16, 0, 255, 0, 0, 0, 0, NULL, NULL, NULL },
83 { d_bitmap_proc, 352, 400, 256, 16, 0, 255, 0, 0, 0, 0, NULL, NULL, NULL },
84 { d_bitmap_proc, 352, 448, 256, 16, 0, 255, 0, 0, 0, 0, NULL, NULL, NULL },
85 { d_box_proc, 170, 170, 300, 140, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
86 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
87 };
88
89
90
91
92
93 /* helper that updates the color box */
update_color_rectangle(int r,int g,int b)94 void update_color_rectangle(int r, int g, int b)
95 {
96 the_dlg[DIALOG_COLOR_BOX].bg = makecol(r, g, b);
97 }
98
99
100
101 /* helper that updates all six color-bar bitmaps according to the
102 * given RGB and HSV values */
update_color_bars(int r,int g,int b,float h,float s,float v)103 void update_color_bars(int r, int g, int b, float h, float s, float v)
104 {
105 int i;
106 int hr,hg,hb; /* Temp RGB values for drawing the HSV sliders */
107
108
109 for (i=0; i<256; i++) {
110 /* Red color-bar */
111 vline(color_bar_bitmap[S_R], i, 0, 15, makecol32(i, g, b));
112
113 /* Green color-bar */
114 vline(color_bar_bitmap[S_G], i, 0, 15, makecol32(r, i, b));
115
116 /* Blue color-bar */
117 vline(color_bar_bitmap[S_B], i, 0, 15, makecol32(r, g, i));
118
119 /* Hue color-bar */
120 hsv_to_rgb(i*360.0f/255.0f, s, v, &hr, &hg, &hb);
121 vline(color_bar_bitmap[S_H], i, 0, 15, makecol32(hr, hg, hb));
122
123 /* Saturation color-bar */
124 hsv_to_rgb(h, i/255.0f, v, &hr, &hg, &hb);
125 vline(color_bar_bitmap[S_S], i, 0, 15, makecol32(hr, hg, hb));
126
127 /* Value color-bar */
128 hsv_to_rgb(h, s, i/255.0f, &hr, &hg, &hb);
129 vline(color_bar_bitmap[S_V], i, 0, 15, makecol32(hr, hg, hb));
130 }
131 }
132
133
134
135 /* helper for reacting to the changing one of the sliders */
update_color_value(void * dp3,int val)136 int update_color_value(void *dp3, int val)
137 {
138 /* 'val' is the value of the slider's position (0-255),
139 'type' is which slider was changed */
140 int type = ((uintptr_t)dp3 - (uintptr_t)colors) / sizeof(colors[0]);
141 int r, g, b;
142 float h, s, v;
143
144 if (colors[type] != val) {
145 colors[type] = val;
146
147 if ((type == S_R) || (type == S_G) || (type == S_B)) {
148 /* The slider that's changed is either R, G, or B.
149 Convert RGB color to HSV. */
150 r = colors[S_R];
151 g = colors[S_G];
152 b = colors[S_B];
153
154 rgb_to_hsv(r, g, b, &h, &s, &v);
155
156 colors[S_H] = h * 255.0f / 360.0f + 0.5f;
157 colors[S_S] = s * 255.0f + 0.5f;
158 colors[S_V] = v * 255.0f + 0.5f;
159 }
160 else {
161 /* The slider that's changed is either H, S, or V.
162 Convert HSV color to RGB. */
163 h = colors[S_H] * 360.0f / 255.0f;
164 s = colors[S_S] / 255.0f;
165 v = colors[S_V] / 255.0f;
166
167 hsv_to_rgb(h, s, v, &r, &g, &b);
168
169 colors[S_R] = r;
170 colors[S_G] = g;
171 colors[S_B] = b;
172 }
173
174 update_color_bars(r,g,b,h,s,v);
175
176 vsync();
177
178 if (get_color_depth() == 8) {
179 /* set the screen background to the new color if in paletted mode */
180 RGB rgb;
181 rgb.r = colors[S_R]>>2;
182 rgb.g = colors[S_G]>>2;
183 rgb.b = colors[S_B]>>2;
184
185 set_color(255, &rgb); /* in 8-bit color modes, we're changing the
186 'white' background-color */
187 }
188
189 /* Update the rectangle in the middle to the new color */
190 update_color_rectangle(r,g,b);
191 object_message(&the_dlg[DIALOG_COLOR_BOX], MSG_DRAW, 0);
192
193 /* Display the updated color-bar bitmaps */
194 object_message(&the_dlg[DIALOG_FIRST_COLOR_BAR], MSG_DRAW, 0);
195 object_message(&the_dlg[DIALOG_FIRST_COLOR_BAR+1], MSG_DRAW, 0);
196 object_message(&the_dlg[DIALOG_FIRST_COLOR_BAR+2], MSG_DRAW, 0);
197 object_message(&the_dlg[DIALOG_FIRST_COLOR_BAR+3], MSG_DRAW, 0);
198 object_message(&the_dlg[DIALOG_FIRST_COLOR_BAR+4], MSG_DRAW, 0);
199 object_message(&the_dlg[DIALOG_FIRST_COLOR_BAR+5], MSG_DRAW, 0);
200 }
201
202 return D_O_K;
203 }
204
205
206
207 /* gui object procedure for the color selection sliders */
my_slider_proc(int msg,DIALOG * d,int c)208 int my_slider_proc(int msg, DIALOG *d, int c)
209 {
210 int *color = (int *)d->dp3;
211
212 switch (msg) {
213
214 case MSG_START:
215 /* initialise the slider position */
216 d->d2 = *color;
217 break;
218
219 case MSG_IDLE:
220 /* has the slider position changed? */
221 if (d->d2 != *color) {
222 d->d2 = *color;
223 object_message(d, MSG_DRAW, 0);
224 }
225 break;
226 }
227
228 return d_slider_proc(msg, d, c);
229 }
230
231
232
main(void)233 int main(void)
234 {
235 int i;
236
237 if (allegro_init() != 0)
238 return 1;
239 install_keyboard();
240 install_mouse();
241 install_timer();
242
243 /* Set the deepest color depth we can set */
244 set_color_depth(32);
245 if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
246 set_color_depth(24);
247 if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
248 set_color_depth(16);
249 if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
250 set_color_depth(15);
251 if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
252 set_color_depth(8);
253 if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
254 allegro_message("Error setting a graphics mode\n%s\n",
255 allegro_error);
256 return 1;
257 }
258 }
259 }
260 }
261 }
262
263 /* In the case we're using an 8-bit color screen, we must set up the palette */
264 if (get_color_depth() == 8) {
265 PALETTE pal332;
266 generate_332_palette(pal332);
267
268 /* Set the palette to the best approximation of a truecolor palette
269 we can get with 8-bit color */
270 set_palette(pal332);
271
272 /* In 8-bit color mode, if there's an RGB table, the sliders
273 will move a lot more smoothly and the updating will be
274 a lot quicker. But if there's no RGB table, this has the
275 advantage that the color conversion routines will take into
276 account any changes in the background color. Instead of
277 changing background color, we could also rely on the colored
278 rectangle like in the other color modes, but using the 3-3-2
279 palette, this doesn't display the color as accurately as
280 changing the background color. */
281 #if 0
282 /* Create an RGB table to speedup makecol8() */
283 create_rgb_table(&rgb_table, pal332, NULL);
284 rgb_map = &rgb_table;
285 #endif
286 }
287
288 clear_to_color(screen,makecol(255,255,255));
289
290 /* color the dialog controls appropriately */
291 /* R -> Red */
292 the_dlg[S_R].fg = the_dlg[DIALOG_NUM_SLIDERS+S_R].fg = makecol(255,0,0);
293 /* G -> Green */
294 the_dlg[S_G].fg = the_dlg[DIALOG_NUM_SLIDERS+S_G].fg = makecol(0,255,0);
295 /* B -> Blue */
296 the_dlg[S_B].fg = the_dlg[DIALOG_NUM_SLIDERS+S_B].fg = makecol(0,0,255);
297
298 /* H -> Grey */
299 the_dlg[S_H].fg = the_dlg[DIALOG_NUM_SLIDERS+S_H].fg = makecol(192,192,192);
300 /* S -> Dark Grey */
301 the_dlg[S_S].fg = the_dlg[DIALOG_NUM_SLIDERS+S_S].fg = makecol(128,128,128);
302 /* V -> Black */
303 the_dlg[S_V].fg = the_dlg[DIALOG_NUM_SLIDERS+S_V].fg = makecol(0,0,0);
304
305 /* Create the bitmaps for the color-bars */
306 for (i=0; i<DIALOG_NUM_SLIDERS; i++) {
307 if (!(color_bar_bitmap[i] = create_bitmap_ex(32,256,16))) {
308 allegro_message("Error creating a color-bar bitmap\n");
309 return 1;
310 }
311
312 the_dlg[DIALOG_FIRST_COLOR_BAR+i].dp = color_bar_bitmap[i];
313 }
314
315 for (i=0; i<DIALOG_NUM_SLIDERS*3; i++)
316 the_dlg[i].bg = makecol(255,255,255);
317
318 the_dlg[DIALOG_COLOR_BOX].fg = makecol(0,0,0);
319
320 textout_ex(screen,font,"RGB<->HSV color spaces example.",344,4,
321 makecol(0,0,0),-1);
322 textout_ex(screen,font,"Drag sliders to change color values.",344,12,
323 makecol(0,0,0),-1);
324
325 textout_ex(screen,font,"The color-bars beneath the sliders",24,384,
326 makecol(128,128,128),-1);
327 textout_ex(screen,font,"show what the resulting color will",24,392,
328 makecol(128,128,128),-1);
329 textout_ex(screen,font,"look like when the slider is",24,400,
330 makecol(128,128,128),-1);
331 textout_ex(screen,font,"dragged to that position.",24,408,
332 makecol(128,128,128),-1);
333
334 switch (get_color_depth()) {
335
336 case 32:
337 textout_ex(screen,font,"Running in truecolor (32-bit 888)",352,24,
338 makecol(128,128,128),-1);
339 textout_ex(screen,font,"16777216 colors",352,32,
340 makecol(128,128,128),-1);
341 break;
342
343 case 24:
344 textout_ex(screen,font,"Running in truecolor (24-bit 888)",352,24,
345 makecol(128,128,128),-1);
346 textout_ex(screen,font,"16777216 colors",352,32,
347 makecol(128,128,128),-1);
348 break;
349
350 case 16:
351 textout_ex(screen,font,"Running in hicolor (16-bit 565)",352,24,
352 makecol(128,128,128),-1);
353 textout_ex(screen,font,"65536 colors",352,32,
354 makecol(128,128,128),-1);
355 break;
356
357 case 15:
358 textout_ex(screen,font,"Running in hicolor (15-bit 555)",352,24,
359 makecol(128,128,128),-1);
360 textout_ex(screen,font,"32768 colors",352,32,
361 makecol(128,128,128),-1);
362 break;
363
364 case 8:
365 textout_ex(screen,font,"Running in paletted mode (8-bit 332)",352,24,
366 makecol(128,128,128),-1);
367 textout_ex(screen,font,"256 colors",352,32,
368 makecol(128,128,128),-1);
369 break;
370
371 default:
372 textout_ex(screen,font,"Unknown color depth",400,16,0,-1);
373 }
374
375 update_color_rectangle(colors[S_R], colors[S_G], colors[S_B]);
376 update_color_bars(colors[S_R], colors[S_G], colors[S_B],
377 colors[S_H]*360.0f/255.0f,
378 colors[S_S]/255.0f, colors[S_V]/255.0f);
379
380 do_dialog(the_dlg, -1);
381
382 for (i=0; i<DIALOG_NUM_SLIDERS; i++)
383 destroy_bitmap(color_bar_bitmap[i]);
384
385 return 0;
386 }
387 END_OF_MAIN()
388