/* The GIMP -- an image manipulation program * Copyright (C) 1995 Spencer Kimball and Peter Mattis * color2bw plugin (C) Regis Rampnoux 2001 * * This program is free software; you can redistribute it and/or modify * it. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * */ /* * todo list: * - add preview * - add spinbuttons for % values */ #include #include #include #include #include #include #include #include #include #include #include /* def pour The Gimp */ static void query (void); static void run (gchar *name, gint nparams, GimpParam *param, gint *nreturn_vals, GimpParam **return_vals); #define PLUGIN_NAME "plug_in_color2bw" GimpPlugInInfo PLUG_IN_INFO = { NULL, /* init_proc */ NULL, /* quit_proc */ query, /* query_proc */ run, /* run_proc */ }; // // definitions pour le plug in // #define DECAL_HORIZONTAL 0 #define DA_WIDTH 300 #define DA_HEIGHT 20 #define RED_PIX 0 #define GREEN_PIX 1 #define BLUE_PIX 2 #define ALPHA_PIX 3 gint color2bw_delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ); void color2bw_aff_bar(GtkWidget *widget, gpointer *bidon ); void color2bw_expo(GtkWidget *widget); void color2bw_draw_triangle(GtkWidget *widget, gint value, gint hauteur, gint bas); void color2bw_choice_triangle(GtkWidget *widget,gpointer *none); void color2bw_aff_value(GtkWidget *widget, gpointer *bidon); void color2bw_maj_triangle(GtkWidget *widget,gpointer *none); void color2bw_cre_boutons(GtkWidget *vbox); void color2bw_destroy( GtkWidget *widget, gpointer *data ); void color2bw_apply_on_image ( void ) ; static gint color2bw_pcr = 100; static gint color2bw_pcg = 100; static gboolean color2bw_pcur = FALSE; static GtkWidget *lib_valeurs ; static gint32 id_image, id_drawable; MAIN () static void query (void) { static GimpParamDef args[] = { { GIMP_PDB_INT32, "run_mode", "Interactive" }, { GIMP_PDB_IMAGE, "image", "Input image" }, { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }, }; static gint nargs = sizeof(args) / sizeof(args[0]); gimp_install_procedure(PLUGIN_NAME, "Convert color pictures to black and white", "grayscale conversion for photos with % of colors", "Regis Rampnoux ", "(C) regis rampnoux", "Version 0.1 dec 2001", "/Filters/Misc/color2bw", "RGB*", GIMP_PLUGIN, nargs, 0, args, NULL); } static void run (gchar *name, gint nparams, GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) { GtkWidget *window; GtkWidget *box; GtkWidget *vbox, *frame, *box2; GtkWidget *rv; static GimpParam values[1]; GimpRunModeType run_mode; GimpPDBStatusType status = GIMP_PDB_SUCCESS; run_mode = param[0].data.d_int32; id_image = param[1].data.d_image; id_drawable = param[2].data.d_int32; values[0].type = GIMP_PDB_STATUS; values[0].data.d_status = status; *nreturn_vals = 1; *return_vals = values; gimp_ui_init("color2bw",TRUE); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "Color to B&W Convert"); gtk_signal_connect (GTK_OBJECT (window), "delete_event", GTK_SIGNAL_FUNC (color2bw_delete_event), NULL); gtk_container_set_border_width (GTK_CONTAINER (window), 10); vbox = gtk_vbox_new(FALSE, 0); box = gtk_hbox_new(FALSE, 0); gtk_container_add (GTK_CONTAINER (window), vbox); gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, FALSE, 0); frame = gtk_aspect_frame_new (NULL,0.0,0.0,0.0,TRUE); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); gtk_box_pack_start (GTK_BOX (box), frame, FALSE, FALSE, 0); rv=gtk_preview_new (GTK_PREVIEW_COLOR); gtk_preview_size (GTK_PREVIEW (rv),DA_WIDTH+ 2 * DECAL_HORIZONTAL, DA_HEIGHT); gtk_container_add (GTK_CONTAINER (frame), rv); gtk_signal_connect (GTK_OBJECT (rv), "expose_event", (GtkSignalFunc) color2bw_aff_bar, NULL); gtk_signal_connect (GTK_OBJECT (rv), "button_press_event", (GtkSignalFunc) color2bw_choice_triangle, NULL); gtk_signal_connect (GTK_OBJECT (rv), "motion_notify_event", (GtkSignalFunc) color2bw_maj_triangle, NULL); gtk_widget_show (rv); gtk_widget_show (frame); gtk_widget_show (box); box2 = gtk_hbox_new(FALSE, 0); lib_valeurs = gtk_label_new(""); gtk_box_pack_start (GTK_BOX (vbox), box2, FALSE, FALSE, 5); gtk_box_pack_start (GTK_BOX (box2),lib_valeurs , FALSE, FALSE, 5); color2bw_aff_value(lib_valeurs, (gpointer *)NULL); gtk_widget_show_all(box2); color2bw_cre_boutons(vbox); gtk_widget_show(vbox); gtk_widget_show (window); gtk_main (); } void color2bw_choice_triangle(GtkWidget *widget,gpointer *none) { gint pos_x, pos_y; gtk_widget_get_pointer(widget,&pos_x, &pos_y); color2bw_pcur = (abs(pos_x - color2bw_pcr) < abs(pos_x - color2bw_pcr - color2bw_pcg)) ? FALSE: TRUE; if (color2bw_pcg == 0 && color2bw_pcr == DA_WIDTH) color2bw_pcur = FALSE; else if (color2bw_pcr == 0 && color2bw_pcg == 0) color2bw_pcur = TRUE; gtk_widget_add_events(widget,GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK ); } void color2bw_maj_triangle(GtkWidget *widget,gpointer *none) { gint pos_x, pos_y; gtk_widget_get_pointer(widget,&pos_x, &pos_y); // on reste dans les limites! if (pos_x < 0) pos_x = 0; else if (pos_x > DA_WIDTH) pos_x = DA_WIDTH; // si la zone verte est vide on choisi le triangle en fonction du sens // du déplacement de la souris (les deux repères sont superposés) if ( !color2bw_pcg ) color2bw_pcur = (pos_x < color2bw_pcr)?FALSE:TRUE; if (color2bw_pcur) color2bw_pcg = pos_x - color2bw_pcr; else { color2bw_pcg = color2bw_pcg - pos_x + color2bw_pcr; color2bw_pcr = pos_x; } if (color2bw_pcg < 0 ) color2bw_pcg = 0; else if (color2bw_pcg + color2bw_pcr > DA_WIDTH) color2bw_pcg = DA_WIDTH - color2bw_pcr; if (color2bw_pcg + color2bw_pcr > DA_WIDTH) { if (color2bw_pcur) color2bw_pcr = DA_WIDTH - color2bw_pcg; else color2bw_pcg = DA_WIDTH - color2bw_pcr; } color2bw_aff_bar(widget, (gpointer *)NULL); color2bw_expo(widget); color2bw_aff_value(lib_valeurs, (gpointer *)NULL); } void color2bw_draw_triangle(GtkWidget *widget, gint value, gint hauteur, gint bas) { GdkPoint points[3]; GdkColor color; GdkColormap *colormap; GdkGC *gc; points[0].x = value - hauteur/2; points[0].y = hauteur+bas; points[1].x = value; points[1].y = 0+bas; points[2].x = value + hauteur/2; points[2].y = hauteur+bas; colormap = gdk_window_get_colormap(widget->window); gc = gdk_gc_new(widget->window); color.red = 0; color.green = 0; color.blue = 0; gdk_color_alloc(colormap,&color); gdk_gc_set_foreground(gc, &color); gdk_draw_polygon( widget->window, gc, TRUE,points,3); gdk_gc_destroy(gc); } void color2bw_aff_value(GtkWidget *widget, gpointer *bidon) { gchar *format_valeur = "Red: %3d%% - Green: %3d%% - Blue: %3d%%"; gchar *lib; lib = g_strdup_printf(format_valeur,(int) color2bw_pcr/3,(int) color2bw_pcg/3,100-(int) color2bw_pcg/3 - (int) color2bw_pcr/3); gtk_label_set_text(GTK_LABEL(widget),lib); gtk_widget_show_all(widget); g_free(lib); } void color2bw_aff_bar(GtkWidget *widget, gpointer *bidon) { GdkColor color; GdkColormap *colormap; GdkGC *gc; gdk_window_clear(widget->window); // creation de la colormap colormap = gdk_window_get_colormap(widget->window); gc = gdk_gc_new(widget->window); color.red = 65535; color.green = 0; color.blue = 0; gdk_color_alloc(colormap,&color); gdk_gc_set_foreground(gc, &color); gdk_draw_rectangle( widget->window, gc, TRUE,DECAL_HORIZONTAL,0, color2bw_pcr,DA_HEIGHT); color.red = 0; color.green = 65535; color.blue = 0; gdk_color_alloc(colormap,&color); gdk_gc_set_foreground(gc, &color); gdk_draw_rectangle( widget->window, gc, TRUE,color2bw_pcr+DECAL_HORIZONTAL,0, color2bw_pcg,DA_HEIGHT); color.red = 0; color.green = 0; color.blue = 65535; gdk_color_alloc(colormap,&color); gdk_gc_set_foreground(gc, &color); gdk_draw_rectangle( widget->window, gc, TRUE,color2bw_pcr+color2bw_pcg+DECAL_HORIZONTAL,0, DA_WIDTH - color2bw_pcg -color2bw_pcr,DA_HEIGHT); gdk_gc_destroy(gc); color2bw_draw_triangle(widget,color2bw_pcr+DECAL_HORIZONTAL,DA_HEIGHT-4,4); color2bw_draw_triangle(widget,color2bw_pcr+color2bw_pcg+DECAL_HORIZONTAL,DA_HEIGHT-4,4); gtk_widget_add_events(widget,GDK_BUTTON_PRESS_MASK); } void color2bw_expo(GtkWidget *widget) { gtk_widget_queue_draw(GTK_WIDGET (widget)); } void color2bw_destroy( GtkWidget *widget, gpointer *data ) { gtk_main_quit(); } gint color2bw_delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) { gtk_main_quit(); return(FALSE); } void color2bw_cre_boutons(GtkWidget *vbox) { GtkWidget *box; GtkWidget *button; box = gtk_hbox_new(FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), box, FALSE, FALSE, 5); button = gtk_button_new_with_label (" OK "); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (color2bw_apply_on_image), (gpointer) NULL); gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 5); gtk_widget_show(button); button = gtk_button_new_with_label (" Quit "); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (color2bw_destroy), (gpointer) "quit"); gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 5); gtk_widget_show(button); gtk_widget_show(box); } void color2bw_apply_on_image(void) { gint32 w0, w, h0, h, h_pr, col, val; GimpPixelRgn srcPR, dstPR; gpointer *pr; guchar *src, *dst, *src_pix, *dst_pix; GimpDrawable *drawable; gboolean alpha; alpha = gimp_drawable_has_alpha(id_drawable); gimp_drawable_mask_bounds(id_drawable,&w0, &h0, &w, &h); drawable = gimp_drawable_get (id_drawable); gimp_pixel_rgn_init (&srcPR, drawable,w0,h0,w-w0,h-h0,FALSE,FALSE); gimp_pixel_rgn_init (&dstPR, drawable,w0,h0,w-w0,h-h0,TRUE,TRUE); for (pr=gimp_pixel_rgns_register(2,&srcPR,&dstPR); pr != NULL; pr = gimp_pixel_rgns_process(pr)) { src = srcPR.data; dst = dstPR.data; h_pr = srcPR.h; while (h_pr--) { src_pix = src; dst_pix = dst; for (col = 0; col < srcPR.w; col++) { val = src_pix[RED_PIX]*color2bw_pcr + src_pix[GREEN_PIX]*color2bw_pcg + src_pix[BLUE_PIX]*(300-color2bw_pcr-color2bw_pcg); dst_pix[RED_PIX]=(unsigned char) (val/300); dst_pix[GREEN_PIX]=(unsigned char) (val/300); dst_pix[BLUE_PIX]=(unsigned char) (val/300); if (alpha) dst_pix[ALPHA_PIX] = src_pix[ALPHA_PIX]; src_pix += srcPR.bpp; dst_pix += dstPR.bpp; } src += srcPR.rowstride; dst += dstPR.rowstride; } } gimp_drawable_merge_shadow (id_drawable,TRUE); gimp_drawable_update(id_drawable,0,0,w,h); gimp_displays_flush(); gtk_main_quit(); }