static void add_pigment (ColorselWater *water, gboolean erase, gdouble x, gdouble y, gdouble much) { GimpColorSelector *selector = GIMP_COLOR_SELECTOR (water); much *= (gdouble) water->pressure_adjust; if (erase) { selector->rgb.r = 1.0 - (1.0 - selector->rgb.r) * (1.0 - much); selector->rgb.g = 1.0 - (1.0 - selector->rgb.g) * (1.0 - much); selector->rgb.b = 1.0 - (1.0 - selector->rgb.b) * (1.0 - much); } else { gdouble r = calc (x, y, 0) / 256.0; gdouble g = calc (x, y, 120) / 256.0; gdouble b = calc (x, y, 240) / 256.0; selector->rgb.r *= (1.0 - (1.0 - r) * much); selector->rgb.g *= (1.0 - (1.0 - g) * much); selector->rgb.b *= (1.0 - (1.0 - b) * much); } gimp_rgb_clamp (&selector->rgb); gimp_rgb_to_hsv (&selector->rgb, &selector->hsv); gimp_color_selector_color_changed (selector); }
static void lic_image (GimpPixelRgn *src_rgn, gint x, gint y, gdouble vx, gdouble vy, GimpRGB *color) { gdouble u, step = 2.0 * l / isteps; gdouble xx = (gdouble) x, yy = (gdouble) y; gdouble c, s; GimpRGB col = { 0, 0, 0, 0 }; GimpRGB col1, col2, col3; /* Get vector at x,y */ /* ================= */ c = vx; s = vy; /* Calculate integral numerically */ /* ============================== */ getpixel (src_rgn, &col1, xx + l * c, yy + l * s); if (source_drw_has_alpha) gimp_rgba_multiply (&col1, filter (-l)); else gimp_rgb_multiply (&col1, filter (-l)); for (u = -l + step; u <= l; u += step) { getpixel (src_rgn, &col2, xx - u * c, yy - u * s); if (source_drw_has_alpha) { gimp_rgba_multiply (&col2, filter (u)); col3 = col1; gimp_rgba_add (&col3, &col2); gimp_rgba_multiply (&col3, 0.5 * step); gimp_rgba_add (&col, &col3); } else { gimp_rgb_multiply (&col2, filter (u)); col3 = col1; gimp_rgb_add (&col3, &col2); gimp_rgb_multiply (&col3, 0.5 * step); gimp_rgb_add (&col, &col3); } col1 = col2; } if (source_drw_has_alpha) gimp_rgba_multiply (&col, 1.0 / l); else gimp_rgb_multiply (&col, 1.0 / l); gimp_rgb_clamp (&col); *color = col; }
/** * gimp_color_hex_entry_set_color: * @entry: a #GimpColorHexEntry widget * @color: pointer to a #GimpRGB * * Sets the color displayed by a #GimpColorHexEntry. If the new color * is different to the previously set color, the "color-changed" * signal is emitted. * * Since: GIMP 2.2 **/ void gimp_color_hex_entry_set_color (GimpColorHexEntry *entry, const GimpRGB *color) { g_return_if_fail (GIMP_IS_COLOR_HEX_ENTRY (entry)); g_return_if_fail (color != NULL); if (gimp_rgb_distance (&entry->color, color) > 0.0) { gchar buffer[8]; guchar r, g, b; gimp_rgb_set (&entry->color, color->r, color->g, color->b); gimp_rgb_clamp (&entry->color); gimp_rgb_get_uchar (&entry->color, &r, &g, &b); g_snprintf (buffer, sizeof (buffer), "%.2x%.2x%.2x", r, g, b); gtk_entry_set_text (GTK_ENTRY (entry), buffer); /* move cursor to the end */ gtk_editable_set_position (GTK_EDITABLE (entry), -1); g_signal_emit (entry, entry_signals[COLOR_CHANGED], 0); } }
static VALUE rb_gimp_rgb_clamp (VALUE self) { GimpRGB result = rb2GimpRGB(self); gimp_rgb_clamp(&result); return GimpRGB2rb(&result); }
GimpRGB get_ray_color_plane (GimpVector3 *pos) { GimpRGB color = background; static gint inside = FALSE; static GimpVector3 ray, spos; static gdouble vx, vy; /* Construct a line from our VP to the point */ /* ========================================= */ gimp_vector3_sub (&ray, pos, &mapvals.viewpoint); gimp_vector3_normalize (&ray); /* Check for intersection. This is a quasi ray-tracer. */ /* =================================================== */ if (plane_intersect (&ray, &mapvals.viewpoint, &spos, &vx, &vy) == TRUE) { color = get_image_color (vx, vy, &inside); if (color.a != 0.0 && inside == TRUE && mapvals.lightsource.type != NO_LIGHT) { /* Compute shading at this point */ /* ============================= */ color = phong_shade (&spos, &mapvals.viewpoint, &mapvals.normal, &mapvals.lightsource.position, &color, &mapvals.lightsource.color, mapvals.lightsource.type); gimp_rgb_clamp (&color); } } if (mapvals.transparent_background == FALSE && color.a < 1.0) { gimp_rgb_composite (&color, &background, GIMP_RGB_COMPOSITE_BEHIND); } return color; }
/** * gimp_scanner_parse_color: * @scanner: A #GScanner created by gimp_scanner_new_file() or * gimp_scanner_new_string() * @dest: Pointer to a color to store the result * * Return value: %TRUE on success * * Since: 2.4 **/ gboolean gimp_scanner_parse_color (GScanner *scanner, GimpRGB *dest) { guint scope_id; guint old_scope_id; GTokenType token; GimpRGB color = { 0.0, 0.0, 0.0, 1.0 }; scope_id = g_quark_from_static_string ("gimp_scanner_parse_color"); old_scope_id = g_scanner_set_scope (scanner, scope_id); if (! g_scanner_scope_lookup_symbol (scanner, scope_id, "color-rgb")) { g_scanner_scope_add_symbol (scanner, scope_id, "color-rgb", GINT_TO_POINTER (COLOR_RGB)); g_scanner_scope_add_symbol (scanner, scope_id, "color-rgba", GINT_TO_POINTER (COLOR_RGBA)); g_scanner_scope_add_symbol (scanner, scope_id, "color-hsv", GINT_TO_POINTER (COLOR_HSV)); g_scanner_scope_add_symbol (scanner, scope_id, "color-hsva", GINT_TO_POINTER (COLOR_HSVA)); } token = G_TOKEN_LEFT_PAREN; while (g_scanner_peek_next_token (scanner) == token) { token = g_scanner_get_next_token (scanner); switch (token) { case G_TOKEN_LEFT_PAREN: token = G_TOKEN_SYMBOL; break; case G_TOKEN_SYMBOL: { gdouble col[4] = { 0.0, 0.0, 0.0, 1.0 }; gint n_channels = 4; gboolean is_hsv = FALSE; gint i; switch (GPOINTER_TO_INT (scanner->value.v_symbol)) { case COLOR_RGB: n_channels = 3; /* fallthrough */ case COLOR_RGBA: break; case COLOR_HSV: n_channels = 3; /* fallthrough */ case COLOR_HSVA: is_hsv = TRUE; break; } token = G_TOKEN_FLOAT; for (i = 0; i < n_channels; i++) { gboolean negate = FALSE; if (g_scanner_peek_next_token (scanner) == '-') { negate = TRUE; g_scanner_get_next_token (scanner); } if (! gimp_scanner_parse_float (scanner, &col[i])) goto finish; if (negate) col[i] = - col[i]; } if (is_hsv) { GimpHSV hsv; gimp_hsva_set (&hsv, col[0], col[1], col[2], col[3]); gimp_hsv_clamp (&hsv); gimp_hsv_to_rgb (&hsv, &color); } else { gimp_rgba_set (&color, col[0], col[1], col[2], col[3]); gimp_rgb_clamp (&color); } token = G_TOKEN_RIGHT_PAREN; } break; case G_TOKEN_RIGHT_PAREN: token = G_TOKEN_NONE; /* indicates success */ goto finish; default: /* do nothing */ break; } } finish: if (token != G_TOKEN_NONE) { g_scanner_get_next_token (scanner); g_scanner_unexp_token (scanner, token, NULL, NULL, NULL, _("fatal parse error"), TRUE); } else { *dest = color; } g_scanner_set_scope (scanner, old_scope_id); return (token == G_TOKEN_NONE); }
/* do the exchanging */ static void exchange (GimpDrawable *drawable, GimpPreview *preview) { GimpPixelRgn srcPR, destPR; guchar min_red, min_green, min_blue; guchar max_red, max_green, max_blue; guchar from_red, from_green, from_blue; guchar to_red, to_green, to_blue; guchar *src_row, *dest_row; gint x, y, bpp = drawable->bpp; gboolean has_alpha; gint x1, y1, y2; gint width, height; GimpRGB min; GimpRGB max; if (preview) { gimp_preview_get_position (preview, &x1, &y1); gimp_preview_get_size (preview, &width, &height); } else if (! gimp_drawable_mask_intersect (drawable->drawable_id, &x1, &y1, &width, &height)) { return; } y2 = y1 + height; has_alpha = gimp_drawable_has_alpha (drawable->drawable_id); /* allocate memory */ src_row = g_new (guchar, drawable->width * bpp); gimp_rgb_get_uchar (&xargs.from, &from_red, &from_green, &from_blue); gimp_rgb_get_uchar (&xargs.to, &to_red, &to_green, &to_blue); /* get boundary values */ min = xargs.from; gimp_rgb_subtract (&min, &xargs.threshold); gimp_rgb_clamp (&min); gimp_rgb_get_uchar (&min, &min_red, &min_green, &min_blue); max = xargs.from; gimp_rgb_add (&max, &xargs.threshold); gimp_rgb_clamp (&max); gimp_rgb_get_uchar (&max, &max_red, &max_green, &max_blue); dest_row = g_new (guchar, drawable->width * bpp); gimp_pixel_rgn_init (&srcPR, drawable, x1, y1, width, height, FALSE, FALSE); gimp_pixel_rgn_init (&destPR, drawable, x1, y1, width, height, (preview == NULL), TRUE); for (y = y1; y < y2; y++) { gimp_pixel_rgn_get_row (&srcPR, src_row, x1, y, width); for (x = 0; x < width; x++) { guchar pixel_red, pixel_green, pixel_blue; guchar new_red, new_green, new_blue; guint idx; /* get current pixel-values */ pixel_red = src_row[x * bpp]; pixel_green = src_row[x * bpp + 1]; pixel_blue = src_row[x * bpp + 2]; idx = x * bpp; /* want this pixel? */ if (pixel_red >= min_red && pixel_red <= max_red && pixel_green >= min_green && pixel_green <= max_green && pixel_blue >= min_blue && pixel_blue <= max_blue) { guchar red_delta, green_delta, blue_delta; red_delta = pixel_red > from_red ? pixel_red - from_red : from_red - pixel_red; green_delta = pixel_green > from_green ? pixel_green - from_green : from_green - pixel_green; blue_delta = pixel_blue > from_blue ? pixel_blue - from_blue : from_blue - pixel_blue; new_red = CLAMP (to_red + red_delta, 0, 255); new_green = CLAMP (to_green + green_delta, 0, 255); new_blue = CLAMP (to_blue + blue_delta, 0, 255); } else { new_red = pixel_red; new_green = pixel_green; new_blue = pixel_blue; } /* fill buffer */ dest_row[idx + 0] = new_red; dest_row[idx + 1] = new_green; dest_row[idx + 2] = new_blue; /* copy alpha-channel */ if (has_alpha) dest_row[idx + 3] = src_row[x * bpp + 3]; } /* store the dest */ gimp_pixel_rgn_set_row (&destPR, dest_row, x1, y, width); /* and tell the user what we're doing */ if (!preview && (y % 10) == 0) gimp_progress_update ((gdouble) y / (gdouble) height); } g_free (src_row); g_free (dest_row); if (preview) { gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview), &destPR); } else { gimp_progress_update (1.0); /* update the processed region */ gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, x1, y1, width, height); } }
GimpRGB get_ray_color_box (GimpVector3 *pos) { GimpVector3 lvp, ldir, vp, p, dir, ns, nn; GimpRGB color, color2; gfloat m[16]; gint i; FaceIntersectInfo face_intersect[2]; color = background; vp = mapvals.viewpoint; p = *pos; /* Translate viewpoint so that the box has its origin */ /* at its lower left corner. */ /* ================================================== */ vp.x = vp.x - mapvals.position.x; vp.y = vp.y - mapvals.position.y; vp.z = vp.z - mapvals.position.z; p.x = p.x - mapvals.position.x; p.y = p.y - mapvals.position.y; p.z = p.z - mapvals.position.z; /* Compute direction */ /* ================= */ gimp_vector3_sub (&dir, &p, &vp); gimp_vector3_normalize (&dir); /* Compute inverse of rotation matrix and apply it to */ /* the viewpoint and direction. This transforms the */ /* observer into the local coordinate system of the box */ /* ==================================================== */ memcpy (m, rotmat, sizeof (gfloat) * 16); transpose_mat (m); vecmulmat (&lvp, &vp, m); vecmulmat (&ldir, &dir, m); /* Ok. Now the observer is in the space where the box is located */ /* with its lower left corner at the origin and its axis aligned */ /* to the cartesian basis. Check if the transformed ray hits it. */ /* ============================================================= */ face_intersect[0].t = 1000000.0; face_intersect[1].t = 1000000.0; if (intersect_box (mapvals.scale, lvp, ldir, face_intersect) == TRUE) { /* We've hit the box. Transform the hit points and */ /* normals back into the world coordinate system */ /* =============================================== */ for (i = 0; i < 2; i++) { vecmulmat (&ns, &face_intersect[i].s, rotmat); vecmulmat (&nn, &face_intersect[i].n, rotmat); ns.x = ns.x + mapvals.position.x; ns.y = ns.y + mapvals.position.y; ns.z = ns.z + mapvals.position.z; face_intersect[i].s = ns; face_intersect[i].n = nn; } color = get_box_image_color (face_intersect[0].face, face_intersect[0].u, face_intersect[0].v); /* Check for total transparency... */ /* =============================== */ if (color.a < 1.0) { /* Hey, we can see through here! */ /* Lets see what's on the other side.. */ /* =================================== */ color = phong_shade (&face_intersect[0].s, &mapvals.viewpoint, &face_intersect[0].n, &mapvals.lightsource.position, &color, &mapvals.lightsource.color, mapvals.lightsource.type); gimp_rgb_clamp (&color); color2 = get_box_image_color (face_intersect[1].face, face_intersect[1].u, face_intersect[1].v); /* Make the normal point inwards */ /* ============================= */ gimp_vector3_mul (&face_intersect[1].n, -1.0); color2 = phong_shade (&face_intersect[1].s, &mapvals.viewpoint, &face_intersect[1].n, &mapvals.lightsource.position, &color2, &mapvals.lightsource.color, mapvals.lightsource.type); gimp_rgb_clamp (&color2); if (mapvals.transparent_background == FALSE && color2.a < 1.0) { gimp_rgb_composite (&color2, &background, GIMP_RGB_COMPOSITE_BEHIND); } /* Compute a mix of the first and second colors */ /* ============================================ */ gimp_rgb_composite (&color, &color2, GIMP_RGB_COMPOSITE_NORMAL); gimp_rgb_clamp (&color); } else if (color.a != 0.0 && mapvals.lightsource.type != NO_LIGHT) { color = phong_shade (&face_intersect[0].s, &mapvals.viewpoint, &face_intersect[0].n, &mapvals.lightsource.position, &color, &mapvals.lightsource.color, mapvals.lightsource.type); gimp_rgb_clamp (&color); } } else { if (mapvals.transparent_background == TRUE) gimp_rgb_set_alpha (&color, 0.0); } return color; }
GimpRGB get_ray_color_sphere (GimpVector3 *pos) { GimpRGB color = background; static GimpRGB color2; static gint inside = FALSE; static GimpVector3 normal, ray, spos1, spos2; static gdouble vx, vy; /* Check if ray is within the bounding box */ /* ======================================= */ if (pos->x<bx1 || pos->x>bx2 || pos->y<by1 || pos->y>by2) return color; /* Construct a line from our VP to the point */ /* ========================================= */ gimp_vector3_sub (&ray, pos, &mapvals.viewpoint); gimp_vector3_normalize (&ray); /* Check for intersection. This is a quasi ray-tracer. */ /* =================================================== */ if (sphere_intersect (&ray, &mapvals.viewpoint, &spos1, &spos2) == TRUE) { /* Compute spherical to rectangular mapping */ /* ======================================== */ gimp_vector3_sub (&normal, &spos1, &mapvals.position); gimp_vector3_normalize (&normal); sphere_to_image (&normal, &vx, &vy); color = get_image_color (vx, vy, &inside); /* Check for total transparency... */ /* =============================== */ if (color.a < 1.0) { /* Hey, we can see through here! */ /* Lets see what's on the other side.. */ /* =================================== */ color = phong_shade (&spos1, &mapvals.viewpoint, &normal, &mapvals.lightsource.position, &color, &mapvals.lightsource.color, mapvals.lightsource.type); gimp_rgb_clamp (&color); gimp_vector3_sub (&normal, &spos2, &mapvals.position); gimp_vector3_normalize (&normal); sphere_to_image (&normal, &vx, &vy); color2 = get_image_color (vx, vy, &inside); /* Make the normal point inwards */ /* ============================= */ gimp_vector3_mul (&normal, -1.0); color2 = phong_shade (&spos2, &mapvals.viewpoint, &normal, &mapvals.lightsource.position, &color2, &mapvals.lightsource.color, mapvals.lightsource.type); gimp_rgb_clamp (&color2); /* Compute a mix of the first and second colors */ /* ============================================ */ gimp_rgb_composite (&color, &color2, GIMP_RGB_COMPOSITE_NORMAL); gimp_rgb_clamp (&color); } else if (color.a != 0.0 && inside == TRUE && mapvals.lightsource.type != NO_LIGHT) { /* Compute shading at this point */ /* ============================= */ color = phong_shade (&spos1, &mapvals.viewpoint, &normal, &mapvals.lightsource.position, &color, &mapvals.lightsource.color, mapvals.lightsource.type); gimp_rgb_clamp (&color); } } if (mapvals.transparent_background == FALSE && color.a < 1.0) { gimp_rgb_composite (&color, &background, GIMP_RGB_COMPOSITE_BEHIND); } return color; }
static GimpRGB phong_shade (GimpVector3 *pos, GimpVector3 *viewpoint, GimpVector3 *normal, GimpVector3 *light, GimpRGB *diff_col, GimpRGB *spec_col, gint type) { GimpRGB ambientcolor, diffusecolor, specularcolor; gdouble NL, RV, dist; GimpVector3 L, NN, V, N; /* Compute ambient intensity */ /* ========================= */ N = *normal; ambientcolor = *diff_col; gimp_rgb_multiply (&ambientcolor, mapvals.material.ambient_int); /* Compute (N*L) term of Phong's equation */ /* ====================================== */ if (type == POINT_LIGHT) gimp_vector3_sub (&L, light, pos); else L = *light; dist = gimp_vector3_length (&L); if (dist != 0.0) gimp_vector3_mul (&L, 1.0 / dist); NL = 2.0 * gimp_vector3_inner_product (&N, &L); if (NL >= 0.0) { /* Compute (R*V)^alpha term of Phong's equation */ /* ============================================ */ gimp_vector3_sub (&V, viewpoint, pos); gimp_vector3_normalize (&V); gimp_vector3_mul (&N, NL); gimp_vector3_sub (&NN, &N, &L); RV = gimp_vector3_inner_product (&NN, &V); RV = pow (RV, mapvals.material.highlight); /* Compute diffuse and specular intensity contribution */ /* =================================================== */ diffusecolor = *diff_col; gimp_rgb_multiply (&diffusecolor, mapvals.material.diffuse_ref); gimp_rgb_multiply (&diffusecolor, NL); specularcolor = *spec_col; gimp_rgb_multiply (&specularcolor, mapvals.material.specular_ref); gimp_rgb_multiply (&specularcolor, RV); gimp_rgb_add (&diffusecolor, &specularcolor); gimp_rgb_multiply (&diffusecolor, mapvals.material.diffuse_int); gimp_rgb_clamp (&diffusecolor); gimp_rgb_add (&ambientcolor, &diffusecolor); } return ambientcolor; }
static VALUE rb_gimp_rgb_clamp_replace (VALUE self) { gimp_rgb_clamp(rb2GimpRGBPtr(self)); return self; }
GimpRGB get_ray_color_no_bilinear_ref (GimpVector3 *position) { GimpRGB color_sum; GimpRGB color_int; GimpRGB light_color; GimpRGB color, env_color; gint x; gdouble xf, yf; GimpVector3 normal, *p, v, r; gint k; gdouble tmpval; pos_to_float (position->x, position->y, &xf, &yf); x = RINT (xf); if (mapvals.bump_mapped == FALSE || mapvals.bumpmap_id == -1) normal = mapvals.planenormal; else normal = vertex_normals[1][(gint) RINT (xf)]; gimp_vector3_normalize (&normal); if (mapvals.transparent_background && heights[1][x] == 0) { gimp_rgb_set_alpha (&color_sum, 0.0); } else { color = peek (RINT (xf), RINT (yf)); color_sum = color; gimp_rgb_multiply (&color_sum, mapvals.material.ambient_int); for (k = 0; k < NUM_LIGHTS; k++) { p = &mapvals.lightsource[k].direction; if (!mapvals.lightsource[k].active || mapvals.lightsource[k].type == NO_LIGHT) continue; else if (mapvals.lightsource[k].type == POINT_LIGHT) p = &mapvals.lightsource[k].position; color_int = mapvals.lightsource[k].color; gimp_rgb_multiply (&color_int, mapvals.lightsource[k].intensity); light_color = phong_shade (position, &mapvals.viewpoint, &normal, p, &color, &color_int, mapvals.lightsource[0].type); } gimp_vector3_sub (&v, &mapvals.viewpoint, position); gimp_vector3_normalize (&v); r = compute_reflected_ray (&normal, &v); /* Get color in the direction of r */ /* =============================== */ sphere_to_image (&r, &xf, &yf); env_color = peek_env_map (RINT (env_width * xf), RINT (env_height * yf)); tmpval = mapvals.material.diffuse_int; mapvals.material.diffuse_int = 0.; light_color = phong_shade (position, &mapvals.viewpoint, &normal, &r, &color, &env_color, DIRECTIONAL_LIGHT); mapvals.material.diffuse_int = tmpval; gimp_rgb_add (&color_sum, &light_color); } gimp_rgb_clamp (&color_sum); return color_sum; }
GimpRGB get_ray_color_no_bilinear (GimpVector3 *position) { GimpRGB color; GimpRGB color_int; GimpRGB color_sum; GimpRGB light_color; gint x; gdouble xf, yf; GimpVector3 normal, *p; gint k; pos_to_float (position->x, position->y, &xf, &yf); x = RINT (xf); if (mapvals.transparent_background && heights[1][x] == 0) { gimp_rgb_set_alpha (&color_sum, 0.0); } else { color = peek (x, RINT (yf)); color_sum = color; gimp_rgb_multiply (&color_sum, mapvals.material.ambient_int); for (k = 0; k < NUM_LIGHTS; k++) { p = &mapvals.lightsource[k].direction; if (!mapvals.lightsource[k].active || mapvals.lightsource[k].type == NO_LIGHT) continue; else if (mapvals.lightsource[k].type == POINT_LIGHT) p = &mapvals.lightsource[k].position; color_int = mapvals.lightsource[k].color; gimp_rgb_multiply (&color_int, mapvals.lightsource[k].intensity); if (mapvals.bump_mapped == FALSE || mapvals.bumpmap_id == -1) { light_color = phong_shade (position, &mapvals.viewpoint, &mapvals.planenormal, p, &color, &color_int, mapvals.lightsource[k].type); } else { normal = vertex_normals[1][x]; light_color = phong_shade (position, &mapvals.viewpoint, &normal, p, &color, &color_int, mapvals.lightsource[k].type); } gimp_rgb_add (&color_sum, &light_color); } } gimp_rgb_clamp (&color_sum); return color_sum; }
static GimpRGB phong_shade (GimpVector3 *position, GimpVector3 *viewpoint, GimpVector3 *normal, GimpVector3 *lightposition, GimpRGB *diff_col, GimpRGB *light_col, LightType light_type) { GimpRGB diffuse_color, specular_color; gdouble nl, rv, dist; GimpVector3 l, v, n, lnormal, h; /* Compute ambient intensity */ /* ========================= */ n = *normal; /* Compute (N*L) term of Phong's equation */ /* ====================================== */ if (light_type == POINT_LIGHT) gimp_vector3_sub (&l, lightposition, position); else { l = *lightposition; gimp_vector3_normalize (&l); } dist = gimp_vector3_length (&l); if (dist != 0.0) gimp_vector3_mul (&l, 1.0 / dist); nl = MAX (0., 2.0 * gimp_vector3_inner_product (&n, &l)); lnormal = l; gimp_vector3_normalize (&lnormal); if (nl >= 0.0) { /* Compute (R*V)^alpha term of Phong's equation */ /* ============================================ */ gimp_vector3_sub (&v, viewpoint, position); gimp_vector3_normalize (&v); gimp_vector3_add (&h, &lnormal, &v); gimp_vector3_normalize (&h); rv = MAX (0.01, gimp_vector3_inner_product (&n, &h)); rv = pow (rv, mapvals.material.highlight); rv *= nl; /* Compute diffuse and specular intensity contribution */ /* =================================================== */ diffuse_color = *light_col; gimp_rgb_multiply (&diffuse_color, mapvals.material.diffuse_int); diffuse_color.r *= diff_col->r; diffuse_color.g *= diff_col->g; diffuse_color.b *= diff_col->b; gimp_rgb_multiply (&diffuse_color, nl); specular_color = *light_col; if (mapvals.material.metallic) /* for metals, specular color = diffuse color */ { specular_color.r *= diff_col->r; specular_color.g *= diff_col->g; specular_color.b *= diff_col->b; } gimp_rgb_multiply (&specular_color, mapvals.material.specular_ref); gimp_rgb_multiply (&specular_color, rv); gimp_rgb_add (&diffuse_color, &specular_color); gimp_rgb_clamp (&diffuse_color); } gimp_rgb_clamp (&diffuse_color); return diffuse_color; }
static void gimp_pick_button_pick (GimpPickButton *button, GdkEvent *event) { GdkScreen *screen = gdk_event_get_screen (event); GimpColorProfile *monitor_profile; GdkMonitor *monitor; GimpRGB rgb; gint x_root; gint y_root; gdouble x_win; gdouble y_win; gdk_window_get_origin (gdk_event_get_window (event), &x_root, &y_root); gdk_event_get_coords (event, &x_win, &y_win); x_root += x_win; y_root += y_win; #ifdef G_OS_WIN32 { HDC hdc; RECT rect; COLORREF win32_color; /* For MS Windows, use native GDI functions to get the pixel, as * cairo does not handle the case where you have multiple monitors * with a monitor on the left or above the primary monitor. That * scenario create a cairo primary surface with negative extent, * which is not handled properly (bug 740634). */ hdc = GetDC (HWND_DESKTOP); GetClipBox (hdc, &rect); win32_color = GetPixel (hdc, x_root + rect.left, y_root + rect.top); ReleaseDC (HWND_DESKTOP, hdc); gimp_rgba_set_uchar (&rgb, GetRValue (win32_color), GetGValue (win32_color), GetBValue (win32_color), 255); } #else { GdkWindow *window; gint x_window; gint y_window; cairo_surface_t *image; cairo_t *cr; guchar *data; guchar color[3]; /* we try to pick from the local window under the cursor, and fall * back to picking from the root window if this fails (i.e., if * the cursor is not under a local window). on wayland, picking * from the root window is not supported, so this at least allows * us to pick from local windows. see bug #780375. */ window = gdk_device_get_window_at_position (gdk_event_get_device (event), &x_window, &y_window); if (! window) { window = gdk_screen_get_root_window (screen); x_window = x_root; y_window = y_root; } image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 1, 1); cr = cairo_create (image); gdk_cairo_set_source_window (cr, window, -x_window, -y_window); cairo_paint (cr); cairo_destroy (cr); data = cairo_image_surface_get_data (image); GIMP_CAIRO_RGB24_GET_PIXEL (data, color[0], color[1], color[2]); cairo_surface_destroy (image); gimp_rgba_set_uchar (&rgb, color[0], color[1], color[2], 255); } #endif monitor = gdk_display_get_monitor_at_point (gdk_screen_get_display (screen), x_root, y_root); monitor_profile = gimp_monitor_get_color_profile (monitor); if (monitor_profile) { GimpColorProfile *srgb_profile; GimpColorTransform *transform; const Babl *format; GimpColorTransformFlags flags = 0; format = babl_format ("R'G'B'A double"); flags |= GIMP_COLOR_TRANSFORM_FLAGS_NOOPTIMIZE; flags |= GIMP_COLOR_TRANSFORM_FLAGS_BLACK_POINT_COMPENSATION; srgb_profile = gimp_color_profile_new_rgb_srgb (); transform = gimp_color_transform_new (monitor_profile, format, srgb_profile, format, GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL, flags); g_object_unref (srgb_profile); if (transform) { gimp_color_transform_process_pixels (transform, format, &rgb, format, &rgb, 1); gimp_rgb_clamp (&rgb); g_object_unref (transform); } } g_signal_emit_by_name (button, "color-picked", &rgb); }