Show excolmap.c syntax highlighted
/*
* Example program for the Allegro library, by Grzegorz Adam Hankiewicz.
*
* This program demonstrates how to create custom graphic effects with
* the al_create_color_table function, this time a greyscale effect.
*/
#include <stdio.h>
#include "allegro.h"
/* AL_RGB -> color mapping table. Not needed, but speeds things up */
AL_RGB_MAP rgb_table;
/* greyscale & negative color mapping table */
AL_COLOR_MAP greyscale_table, negative_table;
AL_PALETTE pal;
AL_BITMAP *background;
AL_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 al_draw_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 AL_PALETTE pal, int x, int y, AL_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 AL_PALETTE pal, int x, int y, AL_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 */
al_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 al_screen using not-greyscale colors */
for (i=0; i<3000; i++)
al_draw_circle_fill(background, rand()%320, rand()%200, rand()%25, 64+rand()%192);
}
int main(void)
{
int x, y, deltax=1, deltay=1;
allegro_init();
al_install_keyboard();
temp = al_create_bitmap(320, 200);
background = al_create_bitmap(320, 200);
generate_background();
/* this isn't needed, but it speeds up the color table calculations */
#ifdef ALLEGRO_CONSOLE_OK
printf("Generating AL_RGB Table (3.25 lines to go)\n");
#endif
al_create_rgb_table(&rgb_table, pal, callback_func);
al_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
al_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
al_create_color_table(&negative_table, pal, return_negative_color, callback_func);
#ifdef ALLEGRO_CONSOLE_OK
printf("\n\n");
#endif
if (al_set_gfx_mode(AL_GFX_SAFE, 320, 200, 0, 0) != 0) {
al_set_gfx_mode(AL_GFX_NONE, 0, 0, 0, 0);
al_show_message("Unable to set any graphic mode\n%s\n", al_error);
return 1;
}
al_set_palette(pal);
/* look, we have set the drawing mode to TRANS. This makes all the drawing
* functions use the general al_color_map table, which is _NOT_ translucent,
* since we are using a custom al_color_map table.
*/
al_drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
al_text_mode(-1);
/* select the greyscale table */
al_color_map = &greyscale_table;
x = y = 50;
al_blit(background, temp, 0, 0, 0, 0, 320, 200);
al_draw_rect_fill(temp, x, y, x+50, y+50, 0);
al_blit(temp, al_screen, 0, 0, 0, 0, 320, 200);
while (!al_key_pressed()) {
x += deltax;
y += deltay;
if ((x < 1) || (x > 320-50))
deltax *= -1;
if ((y < 1) || (y > 200-50))
deltay *= -1;
al_blit(background, temp, 0, 0, 0, 0, 320, 200);
al_put_text_centre(temp, al_font_8x8, "Greyscale effect", AL_SCREEN_W/2, AL_SCREEN_H/2, al_make_color(0, 0, 255));
al_draw_rect_fill(temp, x, y, x+50, y+50, 0);
al_vsync();
al_blit(temp, al_screen, 0, 0, 0, 0, 320, 200);
}
al_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...
*/
al_draw_rect_fill(background, AL_SCREEN_H/4, AL_SCREEN_H/4, background->w-AL_SCREEN_H/4, background->h-AL_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.
*/
al_put_text_centre(background, al_font_8x8, "Negative effect", AL_SCREEN_W/2, AL_SCREEN_H/2, al_make_color(0, 0, 0));
/* switch the active color table... */
al_color_map = &negative_table;
al_blit(background, temp, 0, 0, 0, 0, 320, 200);
al_draw_rect_fill(temp, x, y, x+50, y+50, 0);
al_blit(temp, al_screen, 0, 0, 0, 0, 320, 200);
while (!al_key_pressed()) {
x += deltax;
y += deltay;
if ((x < 1) || (x > 320-50))
deltax *= -1;
if ((y < 1) || (y > 200-50))
deltay *= -1;
al_blit(background, temp, 0, 0, 0, 0, 320, 200);
al_draw_rect_fill(temp, x, y, x+50, y+50, 0);
al_vsync();
al_blit(temp, al_screen, 0, 0, 0, 0, 320, 200);
}
al_destroy_bitmap(background);
al_destroy_bitmap(temp);
return 0;
}
AL_END_OF_MAIN();
See more files for this project here