File: excolmap.c

package info (click to toggle)
allegro4 2%3A4.0.1-1
  • links: PTS
  • area: main
  • in suites: woody
  • size: 17,052 kB
  • ctags: 12,972
  • sloc: ansic: 109,525; asm: 16,672; cpp: 3,221; sh: 1,761; makefile: 556; pascal: 105; perl: 73
file content (231 lines) | stat: -rw-r--r-- 6,109 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/*
 *    Example program for the Allegro library, by Grzegorz Adam Hankiewicz.
 *
 *    This program demonstrates how to create custom graphic effects with
 *    the create_color_table function, this time a greyscale effect.
 */


#include <stdio.h>

#include "allegro.h"



/* RGB -> color mapping table. Not needed, but speeds things up */
RGB_MAP rgb_table;

/* greyscale & negative color mapping table */
COLOR_MAP greyscale_table, negative_table;

PALETTE pal;
BITMAP *background;
BITMAP *temp;



/* progress indicator for the color table calculations */
void callback_func(int pos)
{
   #ifdef ALLEGRO_CONSOLE_OK

      printf(".");
      fflush(stdout);

   #endif
}



/* Here comes our custom function. It's designed to take the input colors
 * (red, green & blue) and return a greyscale color for it. This way, when
 * any drawing function draws say over green, it draws the greyscale color
 * for green.
 * 'pal' is the palette we are looking in to find the colors.
 * Now, imagine we want to draw a pixel with color A, over color B.
 * Once the table is created, set, and the drawing mode is TRANSLUCENT, then
 * A is the 'x' color passed to the function and B is the 'y' color passed
 * to the function.
 * Since we want a greyscale effect with no matter what A (or 'x') color, we
 * ignore it and use y to look at the palette.
 * The x=x line is there to avoid compiler warnings.
 * NOTE:
 * When you return the rgb value, you don't need to search the palette for
 * the nearest color, Allegro does this automatically.
 */

void return_grey_color(AL_CONST PALETTE pal, int x, int y, RGB *rgb)
{
   int c;

   /* first create the greyscale color */
   c = (pal[y].r*0.3 + pal[y].g*0.5 + pal[y].b*0.2);

   /* now assign to our rgb triplet the palette greyscale color... */
   rgb->r = rgb->g = rgb->b = c;
}



/* The negative_color function is quite the same like the grayscale one,
 * since we are ignoring the value of the drawn color (aka x).
 */

void return_negative_color(AL_CONST PALETTE pal, int x, int y, RGB *rgb)
{
   /* to get the negative color, substract the color values of red, green and
    * blue from the full (63) color value
    */
   rgb->r = 63-pal[y].r;
   rgb->g = 63-pal[y].g;
   rgb->b = 63-pal[y].b;
}



void generate_background(void)
{
   int i;

   /* first get some usual colors */
   generate_332_palette(pal);

   /* now remap the first 64 for a perfect greyscale gradient */
   for (i=0; i<64; i++) {
      pal[i].r = i;
      pal[i].g = i;
      pal[i].b = i;
   }

   /* draws some things on the screen using not-greyscale colors */
   for (i=0; i<3000; i++)
      circlefill(background, rand()%320, rand()%200, rand()%25, 64+rand()%192);
}



int main(void)
{
   int x, y, deltax=1, deltay=1;

   allegro_init();
   install_keyboard();

   temp = create_bitmap(320, 200);
   background = create_bitmap(320, 200);

   generate_background();

   /* this isn't needed, but it speeds up the color table calculations */
   #ifdef ALLEGRO_CONSOLE_OK
      printf("Generating RGB Table (3.25 lines to go)\n");
   #endif

   create_rgb_table(&rgb_table, pal, callback_func);
   rgb_map = &rgb_table;

   /* build a color lookup table for greyscale effect */
   #ifdef ALLEGRO_CONSOLE_OK
      printf("\n\nGenerating Greyscale Table (3.25 lines to go)\n");
   #endif

   create_color_table(&greyscale_table, pal, return_grey_color, callback_func);

   /* build a color lookup table for greyscale effect */
   #ifdef ALLEGRO_CONSOLE_OK
      printf("\n\nGenerating Negative Table (3.25 lines to go)\n");
   #endif

   create_color_table(&negative_table, pal, return_negative_color, callback_func);

   #ifdef ALLEGRO_CONSOLE_OK
      printf("\n\n");
   #endif
   
   if (set_gfx_mode(GFX_SAFE, 320, 200, 0, 0) != 0) {
      set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
      allegro_message("Unable to set any graphic mode\n%s\n", allegro_error);
      return 1;
   }
   set_palette(pal);

   /* look, we have set the drawing mode to TRANS. This makes all the drawing
    * functions use the general color_map table, which is _NOT_ translucent,
    * since we are using a custom color_map table.
    */
   drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);

   text_mode(-1);

   /* select the greyscale table */
   color_map = &greyscale_table;

   x = y = 50;
   blit(background, temp, 0, 0, 0, 0, 320, 200);
   rectfill(temp, x, y, x+50, y+50, 0);

   blit(temp, screen, 0, 0, 0, 0, 320, 200);

   while (!keypressed()) {
      x += deltax;
      y += deltay;

      if ((x < 1) || (x > 320-50))
	 deltax *= -1;

      if ((y < 1) || (y > 200-50))
	 deltay *= -1;

      blit(background, temp, 0, 0, 0, 0, 320, 200);
      textout_centre(temp, font, "Greyscale effect", SCREEN_W/2, SCREEN_H/2, makecol(0, 0, 255));
      rectfill(temp, x, y, x+50, y+50, 0);
      vsync();
      blit(temp, screen, 0, 0, 0, 0, 320, 200);
   }

   clear_keybuf();

   /* now it's time for the negative part. The negative example is easier to
    * see with greyscale colors. Therefore we will change the color of the
    * background to a greyscale one, but only in a restricted area...
    */

   rectfill(background, SCREEN_H/4, SCREEN_H/4, background->w-SCREEN_H/4, background->h-SCREEN_H/4, 0);

   /* this should go inside the next loop, but since we won't use the
    * background image any more, we can optimize it's speed printing the
    * text now.
    */
   textout_centre(background, font, "Negative effect", SCREEN_W/2, SCREEN_H/2, makecol(0, 0, 0));

   /* switch the active color table... */
   color_map = &negative_table;

   blit(background, temp, 0, 0, 0, 0, 320, 200);
   rectfill(temp, x, y, x+50, y+50, 0);

   blit(temp, screen, 0, 0, 0, 0, 320, 200);

   while (!keypressed()) {
      x += deltax;
      y += deltay;

      if ((x < 1) || (x > 320-50))
	 deltax *= -1;

      if ((y < 1) || (y > 200-50))
	 deltay *= -1;

      blit(background, temp, 0, 0, 0, 0, 320, 200);
      rectfill(temp, x, y, x+50, y+50, 0);
      vsync();
      blit(temp, screen, 0, 0, 0, 0, 320, 200);
   }

   destroy_bitmap(background);
   destroy_bitmap(temp);

   return 0;
}

END_OF_MAIN();