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