gboolean rcm_gray_motion_notify_event (GtkWidget *widget, GdkEventMotion *event, RcmGray *circle) { gint x, y; GdkGCValues values; values.function = GDK_INVERT; xor_gc = gdk_gc_new_with_values (Current.From->preview->window, &values, GDK_GC_FUNCTION); if (circle->action_flag == DRAG_START) { GtkStyle *style = gtk_widget_get_style (circle->preview); gtk_widget_queue_draw (circle->preview); color_rotate_draw_large_circle (circle->preview->window, style->black_gc, circle->gray_sat); circle->action_flag = DRAGING; } else { color_rotate_draw_little_circle (widget->window, xor_gc, circle->hue, circle->satur); /* erase */ } x = event->x - GRAY_CENTER - LITTLE_RADIUS; y = GRAY_CENTER - event->y + LITTLE_RADIUS; circle->hue = angle_mod_2PI (arctg (y, x)); circle->satur = sqrt (SQR (x) + SQR (y)) / GRAY_RADIUS; if (circle->satur > 1.0) circle->satur = 1; color_rotate_draw_little_circle (widget->window, xor_gc, circle->hue, circle->satur); gtk_spin_button_set_value (GTK_SPIN_BUTTON (circle->hue_entry), circle->hue * rcm_units_factor(Current.Units)); gtk_spin_button_set_value (GTK_SPIN_BUTTON (circle->satur_entry), circle->satur); if (Current.RealTime) rcm_render_preview (Current.Bna->after); gdk_event_request_motions (event); return TRUE; }
float rcm_angle_inside_slice (float angle, RcmAngle *slice) { return angle_mod_2PI (slice->cw_ccw * (slice->beta-angle)) / angle_mod_2PI (slice->cw_ccw * (slice->beta-slice->alpha)); }
static gfloat angle_inside_slice (gfloat hue, gfloat from, gfloat to, gboolean cl) { gint cw_ccw = cl ? -1 : 1; return angle_mod_2PI (cw_ccw * DEG_TO_RAD (to - hue)) / angle_mod_2PI (cw_ccw * DEG_TO_RAD (from - to)); }
float min_prox (float alpha, float beta, float angle) { gfloat temp1 = MIN (angle_mod_2PI (alpha - angle), TP - angle_mod_2PI (alpha - angle)); gfloat temp2 = MIN (angle_mod_2PI (beta - angle), TP - angle_mod_2PI (beta - angle)); return MIN(temp1, temp2); }
gboolean rcm_gray_motion_notify_event (GtkWidget *widget, GdkEventMotion *event, RcmGray *circle) { gint x, y; gtk_widget_queue_draw (circle->preview); x = event->x - GRAY_CENTER - LITTLE_RADIUS; y = GRAY_CENTER - event->y + LITTLE_RADIUS; circle->hue = angle_mod_2PI (arctg (y, x)); circle->satur = sqrt (SQR (x) + SQR (y)) / GRAY_RADIUS; if (circle->satur > 1.0) circle->satur = 1; gtk_spin_button_set_value (GTK_SPIN_BUTTON (circle->hue_entry), circle->hue * rcm_units_factor(Current.Units)); gtk_spin_button_set_value (GTK_SPIN_BUTTON (circle->satur_entry), circle->satur); if (Current.RealTime) rcm_render_preview (Current.Bna->after); gdk_event_request_motions (event); return TRUE; }
float* closest (float *alpha, float *beta, float angle) { gfloat temp_alpha = MIN (angle_mod_2PI (*alpha-angle), TP - angle_mod_2PI (*alpha-angle)); gfloat temp_beta = MIN (angle_mod_2PI (*beta -angle), TP - angle_mod_2PI (*beta -angle)); if (temp_alpha-temp_beta < 0) return alpha; else return beta; }
gboolean rcm_motion_notify_event (GtkWidget *widget, GdkEventMotion *event, RcmCircle *circle) { gfloat clicked_angle, delta; clicked_angle = angle_mod_2PI (arctg (CENTER - event->y, event->x - CENTER)); delta = clicked_angle - circle->prev_clicked; circle->prev_clicked = clicked_angle; if (delta) { if (circle->mode == EACH) { *(circle->target) = clicked_angle; } else { circle->angle->alpha = angle_mod_2PI (circle->angle->alpha + delta); circle->angle->beta = angle_mod_2PI (circle->angle->beta + delta); } gtk_widget_queue_draw (widget); gdk_window_process_updates (gtk_widget_get_window (widget), FALSE); gtk_spin_button_set_value (GTK_SPIN_BUTTON (circle->alpha_entry), circle->angle->alpha * rcm_units_factor(Current.Units)); gtk_spin_button_set_value (GTK_SPIN_BUTTON (circle->beta_entry), circle->angle->beta * rcm_units_factor(Current.Units)); if (Current.RealTime) rcm_render_preview (Current.Bna->after); } gdk_event_request_motions (event); return TRUE; }
gboolean rcm_button_press_event (GtkWidget *widget, GdkEventButton *event, RcmCircle *circle) { float clicked_angle; float *alpha; float *beta; alpha = &circle->angle->alpha; beta = &circle->angle->beta; circle->action_flag = DRAG_START; clicked_angle = angle_mod_2PI (arctg (CENTER - event->y, event->x - CENTER)); circle->prev_clicked = clicked_angle; if ((sqrt (SQR (event->y - CENTER) + SQR (event->x - CENTER)) > RADIUS * EACH_OR_BOTH) && (min_prox (*alpha, *beta, clicked_angle) < G_PI / 12)) { circle->mode = EACH; circle->target = closest (alpha, beta, clicked_angle); if (*(circle->target) != clicked_angle) { GtkStyle *style = gtk_widget_get_style (widget); *(circle->target) = clicked_angle; gtk_widget_queue_draw (circle->preview); color_rotate_draw_arrows (widget->window, style->black_gc, circle->angle); gtk_spin_button_set_value (GTK_SPIN_BUTTON (circle->alpha_entry), circle->angle->alpha * rcm_units_factor(Current.Units)); gtk_spin_button_set_value (GTK_SPIN_BUTTON (circle->beta_entry), circle->angle->beta * rcm_units_factor(Current.Units)); if (Current.RealTime) rcm_render_preview (Current.Bna->after); } } else circle->mode = BOTH; return TRUE; }
static void color_rotate (GeglProperties *o, gfloat *input, gfloat *output) { gfloat h, s, v; gboolean skip = FALSE; rgb_to_hsv (input[0], input[1], input[2], &h, &s, &v); if (is_gray (s, o->threshold)) { if (o->gray_mode == GEGL_COLOR_ROTATE_GRAY_TREAT_AS) { if (angle_inside_slice (o->hue, o->src_from, o->src_to, o->src_clockwise) <= 1) { h = DEG_TO_RAD (o->hue) / TWO_PI; s = o->saturation; } else { skip = TRUE; } } else { skip = TRUE; h = DEG_TO_RAD (o->hue) / TWO_PI; s = o->saturation; } } if (! skip) { h = linear (left_end (o->src_from, o->src_to, o->src_clockwise), right_end (o->src_from, o->src_to, o->src_clockwise), left_end (o->dest_from, o->dest_to, o->dest_clockwise), right_end (o->dest_from, o->dest_to, o->dest_clockwise), h * TWO_PI); h = angle_mod_2PI (h) / TWO_PI; } hsv_to_rgb (h, s, v, output, output + 1, output + 2); }
gboolean rcm_gray_button_press_event (GtkWidget *widget, GdkEventButton *event, RcmGray *circle) { GtkStyle *style = gtk_widget_get_style (widget); int x, y; x = event->x - GRAY_CENTER - LITTLE_RADIUS; y = GRAY_CENTER - event->y + LITTLE_RADIUS; circle->action_flag = DRAG_START; circle->hue = angle_mod_2PI(arctg(y, x)); circle->satur = sqrt (SQR (x) + SQR (y)) / GRAY_RADIUS; if (circle->satur > 1.0) circle->satur = 1; gtk_widget_queue_draw (circle->preview); color_rotate_draw_little_circle (widget->window, style->black_gc, circle->hue, circle->satur); color_rotate_draw_large_circle (circle->preview->window, gtk_widget_get_style (circle->preview)->black_gc, circle->gray_sat); gtk_spin_button_set_value (GTK_SPIN_BUTTON (circle->hue_entry), circle->hue * rcm_units_factor (Current.Units)); gtk_spin_button_set_value (GTK_SPIN_BUTTON (circle->satur_entry), circle->satur); if (Current.RealTime) rcm_render_preview (Current.Bna->after); return TRUE; }
gboolean rcm_motion_notify_event (GtkWidget *widget, GdkEventMotion *event, RcmCircle *circle) { gfloat clicked_angle, delta; gfloat *alpha, *beta; gint cw_ccw; GdkGCValues values; alpha = &(circle->angle->alpha); beta = &(circle->angle->beta); cw_ccw = circle->angle->cw_ccw; delta = angle_mod_2PI (cw_ccw * (*beta - *alpha)); values.function = GDK_INVERT; xor_gc = gdk_gc_new_with_values (Current.From->preview->window, &values, GDK_GC_FUNCTION); clicked_angle = angle_mod_2PI (arctg (CENTER - event->y, event->x - CENTER)); delta = clicked_angle - circle->prev_clicked; circle->prev_clicked = clicked_angle; if (delta) { if (circle->action_flag == DRAG_START) { gtk_widget_queue_draw (circle->preview); circle->action_flag = DRAGING; } else { /* this should be erasing entire angle */ color_rotate_draw_arrows (widget->window, xor_gc, circle->angle); } if (circle->mode == EACH) { *(circle->target)=clicked_angle; } else { circle->angle->alpha=angle_mod_2PI(circle->angle->alpha + delta); circle->angle->beta =angle_mod_2PI(circle->angle->beta + delta); } gdk_window_process_updates (widget->window, FALSE); color_rotate_draw_arrows (widget->window, xor_gc, circle->angle); gtk_spin_button_set_value (GTK_SPIN_BUTTON (circle->alpha_entry), circle->angle->alpha * rcm_units_factor(Current.Units)); gtk_spin_button_set_value (GTK_SPIN_BUTTON (circle->beta_entry), circle->angle->beta * rcm_units_factor(Current.Units)); if (Current.RealTime) rcm_render_preview (Current.Bna->after); } gdk_event_request_motions (event); return TRUE; }
static void color_rotate_row (const guchar *src_row, guchar *dest_row, gint row, gint row_width, gint bytes) { gint col, bytenum; gdouble H, S, V; guchar rgb[3]; for (col = 0; col < row_width; col++) { gboolean skip = FALSE; rgb[0] = src_row[col * bytes + 0]; rgb[1] = src_row[col * bytes + 1]; rgb[2] = src_row[col * bytes + 2]; gimp_rgb_to_hsv4 (rgb, &H, &S, &V); if (rcm_is_gray (S)) { if (Current.Gray_to_from == GRAY_FROM) { if (rcm_angle_inside_slice (Current.Gray->hue, Current.From->angle) <= 1) { H = Current.Gray->hue / TP; S = Current.Gray->satur; } else { skip = TRUE; } } else { skip = TRUE; gimp_hsv_to_rgb4 (rgb, Current.Gray->hue / TP, Current.Gray->satur, V); } } if (! skip) { H = rcm_linear (rcm_left_end (Current.From->angle), rcm_right_end (Current.From->angle), rcm_left_end (Current.To->angle), rcm_right_end (Current.To->angle), H * TP); H = angle_mod_2PI (H) / TP; gimp_hsv_to_rgb4 (rgb, H, S, V); } dest_row[col * bytes + 0] = rgb[0]; dest_row[col * bytes + 1] = rgb[1]; dest_row[col * bytes + 2] = rgb[2]; if (bytes > 3) { for (bytenum = 3; bytenum < bytes; bytenum++) dest_row[col * bytes + bytenum] = src_row[col * bytes + bytenum]; } } }
void rcm_draw_arrows (GdkWindow *window, GdkGC *color, RcmAngle *angle) { gint dist; gfloat alpha, beta, cw_ccw, delta; alpha = angle->alpha; beta = angle->beta; cw_ccw = angle->cw_ccw; delta = angle_mod_2PI(beta - alpha); if (cw_ccw == -1) delta = delta - TP; gdk_draw_line (window,color, CENTER, CENTER, ROUND (CENTER + RADIUS * cos(alpha)), ROUND (CENTER - RADIUS * sin(alpha))); gdk_draw_line( window,color, CENTER + RADIUS * cos(alpha), CENTER - RADIUS * sin(alpha), ROUND (CENTER + RADIUS * REL * cos(alpha - DEL)), ROUND (CENTER - RADIUS * REL * sin(alpha - DEL))); gdk_draw_line (window,color, CENTER + RADIUS * cos(alpha), CENTER - RADIUS * sin(alpha), ROUND (CENTER + RADIUS * REL * cos(alpha + DEL)), ROUND (CENTER - RADIUS * REL * sin(alpha + DEL))); gdk_draw_line (window,color, CENTER, CENTER, ROUND (CENTER + RADIUS * cos(beta)), ROUND (CENTER - RADIUS * sin(beta))); gdk_draw_line (window,color, CENTER + RADIUS * cos(beta), CENTER - RADIUS * sin(beta), ROUND (CENTER + RADIUS * REL * cos(beta - DEL)), ROUND (CENTER - RADIUS * REL * sin(beta - DEL))); gdk_draw_line (window,color, CENTER + RADIUS * cos(beta), CENTER - RADIUS * sin(beta), ROUND (CENTER + RADIUS * REL * cos(beta + DEL)), ROUND (CENTER - RADIUS * REL * sin(beta + DEL))); dist = RADIUS * EACH_OR_BOTH; gdk_draw_line (window,color, CENTER + dist * cos(beta), CENTER - dist * sin(beta), ROUND (CENTER + dist * cos(beta) + cw_ccw * TICK * sin(beta)), ROUND (CENTER - dist * sin(beta) + cw_ccw * TICK * cos(beta))); alpha *= 180 * 64 / G_PI; delta *= 180 * 64 / G_PI; gdk_draw_arc (window, color, 0, CENTER - dist, CENTER - dist, 2*dist, 2*dist, alpha, delta); }
/* render before/after preview */ void rcm_render_preview (GtkWidget *preview) { ReducedImage *reduced; gint version; gint RW, RH, bytes, i, j; guchar *a; guchar *rgb_array; gdouble *hsv_array; gfloat degree; g_return_if_fail (preview != NULL); version = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (preview), "mode")); reduced = Current_c.reduced; RW = reduced->width; RH = reduced->height; bytes = Current_c.drawable->bpp; hsv_array = reduced->hsv; rgb_array = reduced->rgb; a = g_new (guchar, 4 * RW * RH); if (version == CURRENT) { gdouble H, S, V; guchar rgb[3]; for (i = 0; i < RH; i++) { for (j = 0; j < RW; j++) { gboolean unchanged = FALSE; gboolean skip = FALSE; H = hsv_array[i*RW*bytes + j*bytes + 0]; S = hsv_array[i*RW*bytes + j*bytes + 1]; V = hsv_array[i*RW*bytes + j*bytes + 2]; if (rcm_is_gray(S) && (reduced->mask[i*RW+j] != 0)) { switch (Current_c.Gray_to_from) { case GRAY_FROM: if (rcm_angle_inside_slice (Current_c.Gray->hue, Current_c.From->angle) <= 1) { H = Current_c.Gray->hue/TP; S = Current_c.Gray->satur; } else skip = TRUE; break; case GRAY_TO: unchanged = FALSE; skip = TRUE; gimp_hsv_to_rgb4 (rgb, Current_c.Gray->hue/TP, Current_c.Gray->satur, V); break; default: break; } } if (!skip) { unchanged = FALSE; H = rcm_linear (rcm_left_end (Current_c.From->angle), rcm_right_end (Current_c.From->angle), rcm_left_end (Current_c.To->angle), rcm_right_end (Current_c.To->angle), H * TP); H = angle_mod_2PI(H) / TP; gimp_hsv_to_rgb4 (rgb, H,S,V); } if (unchanged) degree = 0; else degree = reduced->mask[i*RW+j] / 255.0; a[(i*RW+j)*4+0] = (1-degree) * rgb_array[i*RW*bytes + j*bytes + 0] + degree * rgb[0]; a[(i*RW+j)*4+1] = (1-degree) * rgb_array[i*RW*bytes + j*bytes + 1] + degree * rgb[1]; a[(i*RW+j)*4+2] = (1-degree) * rgb_array[i*RW*bytes + j*bytes + 2] + degree * rgb[2]; /* apply transparency */ if (bytes == 4) a[(i*RW+j)*4+3] = rgb_array[i*RW*bytes+j*bytes+3]; else a[(i*RW+j)*4+3] = 255; } } } else /* ORIGINAL */ { for (i = 0; i < RH; i++) { for (j = 0; j < RW; j++) { a[(i*RW+j)*4+0] = rgb_array[i*RW*bytes + j*bytes + 0]; a[(i*RW+j)*4+1] = rgb_array[i*RW*bytes + j*bytes + 1]; a[(i*RW+j)*4+2] = rgb_array[i*RW*bytes + j*bytes + 2]; if (bytes == 4) a[(i*RW+j)*4+3] = rgb_array[i*RW*bytes+j*bytes+3]; else a[(i*RW+j)*4+3] = 255; } } } gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview), 0, 0, RW, RH, GIMP_RGBA_IMAGE, a, RW * 4); g_free (a); }