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();
|