예제 #1
0
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);
}
예제 #2
0
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;
}
예제 #3
0
/**
 * 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);
    }
}
예제 #4
0
static VALUE
rb_gimp_rgb_clamp (VALUE self)
{
  GimpRGB result = rb2GimpRGB(self);
  gimp_rgb_clamp(&result);

  return GimpRGB2rb(&result);
}
예제 #5
0
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;
}
예제 #6
0
/**
 * 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);
}
예제 #7
0
/* 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);
    }
}
예제 #8
0
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;
}
예제 #9
0
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;
}
예제 #10
0
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;
}
예제 #11
0
static VALUE
rb_gimp_rgb_clamp_replace (VALUE self)
{
  gimp_rgb_clamp(rb2GimpRGBPtr(self));
  return self;
}
예제 #12
0
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;
}
예제 #13
0
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;
}
예제 #14
0
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;
}
예제 #15
0
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);
}