# Documentation de la bibliothèque MLV-0.6.705

- Presentation
- Téléchargement
- Installation
- Compilation
- Exemples
- API
- Liste des fonctions
- bogues
- contacts

# medium/06_colors.c

Le but de ce programme est de donner un outil simple permettant d'obtenir rapidement le code d'une couleur donnée.

Dans la bibliothèque MLV, le type d'une couleur est MLV_Color. Il s'agit en fait d'en entier codé sur 4 octets, soit 32 bits. Le premier octet code la la composante rouge de la couleur, le deuxième la composante verte, la troisième la composante bleue et la dernière, la composante alpha (transparence).

Ce programme ne constitue pas en soit un tutoriel.

    // This definition are needed by the nearbyint function
    // This definition must appear before #include<stdio.h> and #include<math.h>
    // see the manpages documentation of nearbyint for more information
    #define _ISOC99_SOURCE

    #include <math.h>
    #include<stdio.h>

    #include <MLV/MLV_all.h>

    typedef struct _Color {
            int red;
            int green;
            int blue;
    } Color;

    typedef struct _Point {
            int x;
            int y;
    } Point;

    typedef struct _Triangle {
            Point R;
            Point G;
            Point B;
    } Triangle;

    typedef struct _Graphics {
            int width;
            int height;
            int width_box;
            int height_box;
            int height_bar;
            Triangle triangle;
    } Graphics;

    void saturate_color(
            const Color* color,
            Color* result
    ){
            int max = 1;
            if( (color->red != 0.0 ) || ( color->green != 0.0 ) || ( color->blue != 0.0 ) ){
                    max = color->red;
                    if( max < color->blue ) max = color->blue;
                    if( max < color->green ) max = color->green;
            }
            result->red = (255 * color->red)/max;
            result->green = (255 * color->green)/max;
            result->blue = (255 * color->blue)/max;
    }

    typedef enum {
            INSIDE,
            OUTSIDE
    } Position_in_the_triangle;

    Position_in_the_triangle get_color_of_triangle(
            const Point *cursor, const Triangle * triangle, Color *result
    ){
            double rx,ry,gx,gy,bx,by;
            double determinant;
            double a,b,c;
            Position_in_the_triangle position;

            rx = triangle->R.x - cursor->x;
            gx = triangle->G.x - cursor->x;
            bx = triangle->B.x - cursor->x;
            ry = triangle->R.y - cursor->y;
            gy = triangle->G.y - cursor->y;
            by = triangle->B.y - cursor->y;
            determinant = -(by - gy)*rx + (bx - gx)*ry - bx*gy + by*gx;
            a = (-bx*gy + by*gx)/determinant;
            b = (bx*ry - by*rx)/determinant;
            c = (-gx*ry + gy*rx)/determinant;
            if(
                    ( a < 0.0 ) || ( b < 0.0 ) || ( c < 0.0 )
            ){
                    a = 1/3.0;
                    b = 1/3.0;
                    c = 1/3.0;
                    position = OUTSIDE;
            }else{
                    position = INSIDE;
            }

            int nuance = 255;
            result->red = nearbyint( nuance * a );
            result->green = nearbyint( nuance * b );
            result->blue = nearbyint( nuance * c );
            return position;
    }

    void get_color_of_bar(
            const Point* cursor, const Graphics* graphics,
            const  Color* bar_color, Color* result
    ){

            Color satured_color;
            saturate_color( bar_color, &satured_color );

            double nuance = (cursor->x)/ (double) graphics->width;
            result->red = nearbyint( nuance * satured_color.red );
            result->green = nearbyint( nuance * satured_color.green );
            result->blue = nearbyint( nuance * satured_color.blue );
    }

    typedef enum {
            TRIANGLE,
            BAR
    } Click_position;

    Click_position get_color(
            const Point* cursor,
            const Graphics* graphics,
            const Color * bar_color,
            Color * result
    ){
            if( cursor->y >= graphics->height- graphics->height_bar ){
                    get_color_of_bar(       cursor, graphics, bar_color, result     );
                    return BAR;
            }else{
                    get_color_of_triangle( cursor, &(graphics->triangle), result );
                    return TRIANGLE;
            }
    }

    void draw_text(
            const Color *color, const Graphics * graphics, int y_translation
    ){
            int size_text = 28;
            char text[size_text];
            snprintf(
                    text, size_text, "R:%d, G:%d, B:%d, A:%d ",
                    color->red, color->green, color->blue, MLV_ALPHA_OPAQUE
            );
            int text_width,text_height;
            MLV_get_size_of_text( text, &text_width, &text_height );

            MLV_draw_text(
                    graphics->width - graphics->width_box - text_width,
                    (graphics->height_box/2) - (text_height/2) + y_translation ,
                    text,
                    MLV_COLOR_RED
            );
    }

    void draw_foreground(
            const Point *cursor, const Graphics * graphics, const Color* bar_color
    ){
            MLV_load_screen();

            Color cursor_color;

            get_color( cursor, graphics, bar_color, &cursor_color );

            MLV_draw_filled_rectangle(
                    graphics->width-graphics->width_box,0,
                    graphics->width_box,graphics->height_box,
                    MLV_rgba(
                            cursor_color.red, cursor_color.green, cursor_color.blue,
                            MLV_ALPHA_OPAQUE
                    )
            );

            draw_text( &cursor_color, graphics, 0 );

            MLV_actualise_window();
    }

    void draw_background(
            const Graphics * graphics,
            const Color* bar_color,
            const Color* selection_color
    ){
            int width = graphics->width;
            int height = graphics->height;
            int height_bar = graphics->height_bar;
            Point point;
            Color color;
            MLV_draw_filled_rectangle( 0, 0, width, height, MLV_COLOR_BLACK );
            for( point.x = 0; point.x< width; point.x++){
                    for( point.y=0; point.y<height;point.y++ ){
                            if(
                                    get_color_of_triangle(
                                            &point, &(graphics->triangle), &color
                                    ) == INSIDE
                            ){
                                    MLV_draw_point(
                                            point.x, point.y,
                                            MLV_rgba(
                                                    color.red, color.green, color.blue,
                                                    MLV_ALPHA_OPAQUE
                                            )
                                    );
                            }
                    }
            }
            int i;

            Color bar_color_satured;
            saturate_color( bar_color, &bar_color_satured );

            for( i=0; i<width; i++ ){
                    MLV_Color color = MLV_rgba(
                            (bar_color_satured.red*i)/width ,
                            (bar_color_satured.green*i)/width,
                            (bar_color_satured.blue*i)/width,
                            MLV_ALPHA_OPAQUE
                    );
                    MLV_draw_line( i, height-height_bar, i, height, color );
            }
            MLV_draw_filled_rectangle(
                    graphics->width-graphics->width_box,
                    graphics->height_box, graphics->width_box,graphics->height_box,
                    MLV_rgba(
                            selection_color->red, selection_color->green, selection_color->blue,
                            MLV_ALPHA_OPAQUE
                    )
            );

            draw_text( selection_color, graphics, graphics->height_box );

            MLV_save_screen();
    }

    void set_triangle( Graphics * graphics, int posx, int posy, int size ){
            int height = size*sqrt(3)/2.0;
            graphics->triangle.R.x = posx;
            graphics->triangle.R.y = posy + height;
            graphics->triangle.G.x = posx + size;
            graphics->triangle.G.y = posy + height;
            graphics->triangle.B.x = posx + size/2;
            graphics->triangle.B.y = posy;
    }

    int main( int argc, char *argv[] ){
            Graphics graphics;
                    graphics.width=640; graphics.height=480;
                    graphics.width_box=120; graphics.height_box=80;
                    graphics.height_bar = 40;
                    set_triangle( &graphics, 50, 100, 300 );
            Point cursor; cursor.x = 0; cursor.y = 0;
            MLV_Button_state state;
            MLV_Keyboard_button key;
            Color selection_color;
            get_color_of_triangle( &cursor, &(graphics.triangle), &selection_color );
            Color bar_color = selection_color;

            MLV_Event event = MLV_NONE;

            MLV_create_window(
                    "medium - 6 - colors", "colors", graphics.width, graphics.height
            );

            draw_background( &graphics, &bar_color, &selection_color );
            draw_foreground( &cursor, &graphics, &bar_color );
            while( !( event == MLV_KEY && key == MLV_KEYBOARD_ESCAPE ) ){
                    event = MLV_get_event(
                            &key, NULL, NULL,
                            NULL, NULL,
                            &(cursor.x), &(cursor.y), NULL,
                            &state
                    );
                    switch( event ){
                            case MLV_MOUSE_MOTION :
                                    draw_foreground( &cursor, &graphics, &bar_color );
                                    break;
                            case MLV_MOUSE_BUTTON :
                                    if( state == MLV_PRESSED ){
                                            if(
                                                    get_color(
                                                            &cursor, &graphics, &bar_color, &selection_color
                                                    ) == TRIANGLE
                                            ){
                                                    bar_color = selection_color;
                                            }
                                            printf(
                                                    "MLV_rgba( %d , %d , %d, MLV_ALPHA_OPAQUE )\n",
                                                    selection_color.red, selection_color.green,
                                                    selection_color.blue
                                            );

                                            draw_background( &graphics, &bar_color, &selection_color );
                                            draw_foreground( &cursor, &graphics, &bar_color );
                                    };
                                    break;
                            default:;
                    }
            }
            MLV_free_window();

            return 0;
    }