HTMLify

Color Picker
Views: 9 | Author: abh
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk/gdkevents.h>
#include <stdio.h>

// main color
unsigned char R = 255, G = 0, B = 0;
unsigned char s_r = 255, s_g = 0, s_b = 0;
int H; // Hue

void update_color(unsigned char r, unsigned char g, unsigned char b) {
    R = r, G = g, B = b;
    // gtk_scale_set_digits(GTK_SCALE(r_scale), 6);
}

void hue_to_RGB(int H, guchar *R, guchar *G, guchar *B) {
}

void HSV_to_RGB(int H, int S, int V, guchar *R, guchar *G, guchar *B) {

}

void color_for(int x, int y, const unsigned char base_r, const unsigned char base_g, const unsigned char base_b, guchar *r, guchar *g, guchar *b) {
    double 
        s = (double)x/256,
        v = (double)y/256
    ;
    int e;

    if (s < 0) s = 0;
    if (s > 1) s = 1;
    if (v < 0) v = 0;
    if (v > 1) v = 1;

    e = (int)((-s+v)*255);

    if (base_r + e > 255)
        *r = 255;
    else if (base_r + e < 0)
        *r = 0;
    else
        *r = base_r + e;

    if (base_g + e > 255)
        *g = 255;
    else if (base_g + e < 0)
        *g = 0;
    else
        *g = base_g + e;

    if (base_b + e > 255)
        *b = 255;
    else if (base_b + e < 0)
        *b = 0;
    else
        *b = base_b + e;

}

void fill_color_grid(GdkPixbuf *grid, const unsigned char base_r, const unsigned char base_g, const unsigned char base_b) {
    int w = 256, h = 256, i, j, k, rs, n_c;
    guchar *pixel, *pixels = gdk_pixbuf_get_pixels(grid);
    guchar r, g, b;
    rs = gdk_pixbuf_get_rowstride(grid);
    n_c = gdk_pixbuf_get_n_channels(grid);
    for (i=0; i<h; i++) {
            
        for (j=0; j<w; j++) {
            pixel = pixels + i*rs + j*n_c;

            color_for(j, i, base_r, base_g, base_b, &r, &g, &b);

            pixel[0] = r;//%256;//base_r + (i*2); 
            pixel[1] = g;//%256;//base_g + (j);
            pixel[2] = b;//%256;//base_b + (j);
        }
    }
}

void fill_select_color_grid(GdkPixbuf *grid) {
    int w = 90, h = 30, i, j, rs, n_c;
    guchar *pixel, *pixels = gdk_pixbuf_get_pixels(grid);
    rs = gdk_pixbuf_get_rowstride(grid);
    n_c = gdk_pixbuf_get_n_channels(grid);
    for (i=0; i<h; i++) {
        for (j=0; j<w; j++) {
            pixel = pixels + i*rs + j*n_c;
            pixel[0] = s_r;
            pixel[1] = s_g;
            pixel[2] = s_b;
        }
    }
}

gboolean auto_update_color_grid(gpointer image_p) {
    GdkPixbuf *color_grid = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, 256, 256);
    GtkWidget *image = GTK_WIDGET(image_p);
    fill_color_grid(color_grid, R, G, B);
    gtk_image_set_from_pixbuf(GTK_IMAGE(image), color_grid);
    return TRUE;
}

gboolean auto_update_select_color(gpointer image_p) {
    GdkPixbuf *color_grid = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, 90, 30);
    GtkWidget *image = GTK_WIDGET(image_p);
    fill_select_color_grid(color_grid);
    gtk_image_set_from_pixbuf(GTK_IMAGE(image), color_grid);
    return TRUE;
}

gboolean auto_sync_selected_color(gpointer elements) {
    GPtrArray *array = elements;
    GtkRange
        *r_scale = g_ptr_array_index(array, 0),
        *g_scale = g_ptr_array_index(array, 1),
        *b_scale = g_ptr_array_index(array, 2)
    ;
    GtkEditable
        *r_entry = g_ptr_array_index(array, 3),
        *g_entry = g_ptr_array_index(array, 4),
        *b_entry = g_ptr_array_index(array, 5),
        *html_notation_entry = g_ptr_array_index(array, 6)
    ;
    char buf[10];

    gtk_range_set_value(r_scale, (double)s_r);
    gtk_range_set_value(g_scale, (double)s_g);
    gtk_range_set_value(b_scale, (double)s_b);

    sprintf(buf, "%.2f", (double)s_r);
    gtk_editable_set_text(r_entry, buf);
    sprintf(buf, "%.2f", (double)s_g);
    gtk_editable_set_text(g_entry, buf);
    sprintf(buf, "%.2f", (double)s_b);
    gtk_editable_set_text(b_entry, buf);

    sprintf(buf, "#%02X%02X%02X", s_r, s_g, s_b);
    gtk_editable_set_text(html_notation_entry, buf);

    return TRUE;
}

void on_color_select(GtkGestureClick *gesture, int n_p, double x, double y, GtkWidget *color_grid) {
    // g_print("click detected on x: %f y: %f \n", x, y);
    // GtkAllocation alloc;
    // int cx, cy;
    // gtk_widget_get_allocation(color_grid, &alloc);
    // cx = ((x - alloc.x)/alloc.width)*255;
    // cy = ((y - alloc.y)/alloc.height)*255;
    color_for(x, y, R, G, B, &s_r, &s_g, &s_b);
    // g_print("calculated cx: %d, yx: %d\n", cx, cy);
}

void on_color_bar_scale_change(GtkRange *scale, gpointer *image) {
    unsigned char r = 255, g = 0, b = 0;
    int value = gtk_range_get_value(GTK_RANGE(scale));

    if (value && value >= 256) {
        b += 255;
        value -= 256;
    } else if (value) {
        b += value-1;
        value = 0;
    }

    if (value && value >= 256) {
        r -= 255;
        value -= 256;
    } else if (value) {
        r -= value-1;
        value = 0;
    }
    
    if (value && value >= 256) {
        g += 255;
        value -= 256;
    } else if (value) {
        g += value-1;
        value = 0;
    }
    
    if (value && value >= 256) {
        b -= 255;
        value -= 256;
    } else if (value) {
        b -= value-1;
        value = 0;
    }

    if (value && value >= 256) {
        r += 255;
        value -= 256;
    } else if (value) {
        r -= value-1;
        value = 0;
    }
    
    if (value && value >= 256) {
        g -= 255;
        value -= 256;
    } else if (value) {
        g -= value-1;
        value = 0;
    }

    R = r, G = g, B = b;
    s_r = r, s_g = g, s_b = b;
}

void on_color_scale_change(GtkRange *scale, gpointer *entry) {
    double value = gtk_range_get_value(scale);
    char c = gtk_widget_get_name(GTK_WIDGET(scale))[0];
    switch (c) {
        case 'r':
            s_r = (guchar)value;
            break;
        case 'g':
            s_g = (guchar)value;
            break;
        case 'b':
            s_b = (guchar)value;
            break;
    }
}

void on_color_entry_activate(GtkEditable *entry, GtkRange *scale) {
    const char *text = gtk_editable_get_text(entry);
    float value;
    int i=0;
    bool is_num=true;
    while (text[i] != '\0') {
        if (text[i] < '0' || text[i] > '9') {
            is_num = false;
            break;
        }
        i++;
    }
    if (is_num) {
        char c = gtk_widget_get_name(GTK_WIDGET(entry))[0];
        switch (c) {
            case 'r':
                s_r = (guchar)value; break;
            case 'g':
                s_g = (guchar)value; break;
            case 'b':
                s_b = (guchar)value; break;
        }
    }
}

void on_app_activate(GtkApplication *app, gpointer null_value) {
    GtkWidget
        *window = gtk_application_window_new(app),
        *master_div = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2),
        *left_pane = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2),
        *color_grid_image = gtk_image_new(),
        *color_bar = gtk_scale_new_with_range(GTK_ORIENTATION_VERTICAL, 1, 256*6, 1),
        *right_pane = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1),
        *r_pack_div = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3),
        *g_pack_div = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3),
        *b_pack_div = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3),
        *r_label = gtk_label_new("R"),
        *g_label = gtk_label_new("G"),
        *b_label = gtk_label_new("B"),
        *r_scale = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 255, 1),
        *g_scale = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 255, 1),
        *b_scale = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 255, 1),
        *r_entry = gtk_entry_new(),
        *g_entry = gtk_entry_new(),
        *b_entry = gtk_entry_new(),
        *html_notation_pack_div = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3),
        *selected_color_image = gtk_image_new(),
        *html_notation_label = gtk_label_new("HTML Notation:"),
        *html_notation_entry = gtk_entry_new()
    ;

    GtkEventController *click = GTK_EVENT_CONTROLLER(gtk_gesture_click_new());

    GdkPixbuf *color_grid = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, 256, 256);
    GdkPixbuf *s_color_grid = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, 90, 30);
    
    // left pane packing
    gtk_widget_set_valign(color_grid_image, GTK_ALIGN_START);
    gtk_widget_set_halign(color_grid_image, GTK_ALIGN_START);
    gtk_widget_set_size_request(color_grid_image, 256, 256);
    gtk_widget_set_hexpand(color_grid_image, true);
    gtk_widget_set_name(color_bar, "color-bar");

    gtk_box_append(GTK_BOX(left_pane), color_grid_image);
    gtk_box_append(GTK_BOX(left_pane), color_bar);


    // right pane packing
    gtk_widget_set_hexpand(r_scale, true);
    gtk_widget_set_hexpand(g_scale, true);
    gtk_widget_set_hexpand(b_scale, true);

    gtk_widget_set_name(r_scale, "r-scale");
    gtk_widget_set_name(g_scale, "g-scale");
    gtk_widget_set_name(b_scale, "b-scale");

    gtk_widget_set_name(r_entry, "r-ently");
    gtk_widget_set_name(g_entry, "g-ently");
    gtk_widget_set_name(b_entry, "b-ently");

    gtk_box_append(GTK_BOX(r_pack_div), r_label);
    gtk_box_append(GTK_BOX(r_pack_div), r_scale);
    gtk_box_append(GTK_BOX(r_pack_div), r_entry);
    gtk_box_append(GTK_BOX(g_pack_div), g_label);
    gtk_box_append(GTK_BOX(g_pack_div), g_scale);
    gtk_box_append(GTK_BOX(g_pack_div), g_entry);
    gtk_box_append(GTK_BOX(b_pack_div), b_label);
    gtk_box_append(GTK_BOX(b_pack_div), b_scale);
    gtk_box_append(GTK_BOX(b_pack_div), b_entry);

    gtk_box_append(GTK_BOX(right_pane), r_pack_div);
    gtk_box_append(GTK_BOX(right_pane), g_pack_div);
    gtk_box_append(GTK_BOX(right_pane), b_pack_div);

    gtk_widget_set_size_request(selected_color_image, 90, 60);
    gtk_widget_set_hexpand(selected_color_image, true);
    // gtk_widget_set_vexpand(selected_color_image, true);
    gtk_editable_set_editable(GTK_EDITABLE(html_notation_entry), false);
    gtk_box_append(GTK_BOX(html_notation_pack_div), selected_color_image);
    gtk_box_append(GTK_BOX(html_notation_pack_div), html_notation_label);
    gtk_box_append(GTK_BOX(html_notation_pack_div), html_notation_entry);
    gtk_box_append(GTK_BOX(right_pane), html_notation_pack_div);


    // master div packing
    gtk_box_append(GTK_BOX(master_div), left_pane);
    gtk_box_append(GTK_BOX(master_div), right_pane);
    
    // signals
    g_signal_connect(click, "pressed", G_CALLBACK(on_color_select), color_grid_image);
    g_signal_connect(color_bar, "value-changed", G_CALLBACK(on_color_bar_scale_change), color_grid_image);

    g_signal_connect(r_scale, "value-changed", G_CALLBACK(on_color_scale_change), r_entry);
    g_signal_connect(g_scale, "value-changed", G_CALLBACK(on_color_scale_change), g_entry);
    g_signal_connect(b_scale, "value-changed", G_CALLBACK(on_color_scale_change), b_entry);

    g_signal_connect(r_entry, "activate", G_CALLBACK(on_color_entry_activate), r_scale);
    g_signal_connect(g_entry, "activate", G_CALLBACK(on_color_entry_activate), g_scale);
    g_signal_connect(b_entry, "activate", G_CALLBACK(on_color_entry_activate), b_scale);

    gtk_widget_add_controller(color_grid_image, click);
    
    GPtrArray *elements = g_ptr_array_new();
    g_ptr_array_add(elements, r_scale);
    g_ptr_array_add(elements, g_scale);
    g_ptr_array_add(elements, b_scale);
    g_ptr_array_add(elements, r_entry);
    g_ptr_array_add(elements, g_entry);
    g_ptr_array_add(elements, b_entry);
    g_ptr_array_add(elements, html_notation_entry);

    g_timeout_add_seconds(1/5, auto_update_color_grid, color_grid_image);
    g_timeout_add_seconds(1/5, auto_update_select_color, selected_color_image);
    g_timeout_add_seconds(1/5, auto_sync_selected_color, elements);

    // main window
    gtk_window_set_child(GTK_WINDOW(window), master_div);
    gtk_window_set_default_size(GTK_WINDOW(window), 650, 300);
    gtk_widget_set_visible(window, true);



        // CSS Provider
    GtkCssProvider *provider = gtk_css_provider_new();
    gtk_css_provider_load_from_data(provider,
        "#color-bar {"
        "   background-image: linear-gradient(#ff0000, #ff00ff, #0000ff, #00ffff, #00ff00, #ffff00, #ff0000);"
        "}"
        "#color-bar slider {"
        "   opacity: 0;"
        "}"
        , -1);

    // Apply CSS to screen
    GtkStyleContext *context;
    context = gtk_widget_get_style_context(window);
    gtk_style_context_add_provider_for_display(
        gdk_display_get_default(),
        GTK_STYLE_PROVIDER(provider),
        GTK_STYLE_PROVIDER_PRIORITY_USER
    );
}

int main(int argc, char **argv) {
    GtkApplication *app = gtk_application_new("sir.kk.for.color-picker", 0);
    g_signal_connect(app, "activate", G_CALLBACK(on_app_activate), NULL);
    return g_application_run(G_APPLICATION(app), argc, argv);
}

Comments