예제 #1
0
파일: gimpcagetool.c 프로젝트: STRNG/gimp
static gint
gimp_cage_tool_is_on_edge (GimpCageTool *ct,
                           gdouble       x,
                           gdouble       y,
                           gint          handle_size)
{
  GimpCageOptions *options = GIMP_CAGE_TOOL_GET_OPTIONS (ct);
  GimpCageConfig  *config  = ct->config;
  gint             i;
  guint            n_cage_vertices;
  GimpVector2      A, B, C, AB, BC, AC;
  gdouble          lAB, lBC, lAC, lEB, lEC;

  g_return_val_if_fail (GIMP_IS_CAGE_TOOL (ct), -1);

  n_cage_vertices = gimp_cage_config_get_n_points (config);

  if (n_cage_vertices < 2)
    return -1;

  A = gimp_cage_config_get_point_coordinate (config,
                                             options->cage_mode,
                                             n_cage_vertices-1);
  B = gimp_cage_config_get_point_coordinate (config,
                                             options->cage_mode,
                                             0);
  C.x = x;
  C.y = y;

  for (i = 0; i < n_cage_vertices; i++)
    {
      gimp_vector2_sub (&AB, &A, &B);
      gimp_vector2_sub (&BC, &B, &C);
      gimp_vector2_sub (&AC, &A, &C);

      lAB = gimp_vector2_length (&AB);
      lBC = gimp_vector2_length (&BC);
      lAC = gimp_vector2_length (&AC);
      lEB = lAB / 2 + (SQR (lBC) - SQR (lAC)) / (2 * lAB);
      lEC = sqrt (SQR (lBC) - SQR (lEB));

      if ((lEC < handle_size / 2) && (abs (SQR (lBC) - SQR (lAC)) <= SQR (lAB)))
        return i;

      A = B;
      B = gimp_cage_config_get_point_coordinate (config,
                                                 options->cage_mode,
                                                 (i+1) % n_cage_vertices);
    }

  return -1;
}
예제 #2
0
파일: gimpvector.c 프로젝트: LebedevRI/gimp
/**
 * gimp_vector2_normalize:
 * @vector: a pointer to a #GimpVector2.
 *
 * Normalizes the @vector so the length of the @vector is 1.0. The nul
 * vector will not be changed.
 **/
void
gimp_vector2_normalize (GimpVector2 *vector)
{
  gdouble len;

  len = gimp_vector2_length (vector);

  if (len != 0.0)
    {
      len = 1.0 / len;
      vector->x *= len;
      vector->y *= len;
    }
  else
    {
      *vector = gimp_vector2_zero;
    }
}
예제 #3
0
파일: gimp-utils.c 프로젝트: Natella/gimp
/**
 * gimp_utils_point_to_line_distance:
 * @point:              The point to calculate the distance for.
 * @point_on_line:      A point on the line.
 * @line_direction:     Normalized line direction vector.
 * @closest_line_point: Gets set to the point on the line that is
 *                      closest to @point.
 *
 * Returns: The shortest distance from @point to the line defined by
 *          @point_on_line and @normalized_line_direction.
 **/
static gdouble
gimp_utils_point_to_line_distance (const GimpVector2 *point,
                                   const GimpVector2 *point_on_line,
                                   const GimpVector2 *line_direction,
                                   GimpVector2       *closest_line_point)
{
  GimpVector2 distance_vector;
  GimpVector2 tmp_a;
  GimpVector2 tmp_b;
  gdouble     d;

  gimp_vector2_sub (&tmp_a, point, point_on_line);

  d = gimp_vector2_inner_product (&tmp_a, line_direction);

  tmp_b = gimp_vector2_mul_val (*line_direction, d);

  *closest_line_point = gimp_vector2_add_val (*point_on_line,
                                              tmp_b);

  gimp_vector2_sub (&distance_vector, closest_line_point, point);

  return gimp_vector2_length (&distance_vector);
}
예제 #4
0
static gboolean
gimp_operation_cage_coef_calc_process (GeglOperation       *operation,
                                       GeglBuffer          *output,
                                       const GeglRectangle *roi)
{
  GimpOperationCageCoefCalc *occc   = GIMP_OPERATION_CAGE_COEF_CALC (operation);
  GimpCageConfig            *config = GIMP_CAGE_CONFIG (occc->config);

  Babl *format = babl_format_n (babl_type ("float"), 2 * gimp_cage_config_get_n_points (config));

  GeglBufferIterator *it;
  guint               n_cage_vertices;
  GimpCagePoint      *current, *last;

  if (! config)
    return FALSE;

  n_cage_vertices   = gimp_cage_config_get_n_points (config);

  it = gegl_buffer_iterator_new (output, roi, format, GEGL_BUFFER_READWRITE);

  while (gegl_buffer_iterator_next (it))
    {
      /* iterate inside the roi */
      gint  n_pixels = it->length;
      gint  x = it->roi->x; /* initial x                   */
      gint  y = it->roi->y; /*           and y coordinates */
      gint  j;

      gfloat      *coef = it->data[0];

      while(n_pixels--)
        {
          if (gimp_cage_config_point_inside(config, x, y))
            {
              last = &(g_array_index (config->cage_points, GimpCagePoint, 0));

              for( j = 0; j < n_cage_vertices; j++)
                {
                  GimpVector2 v1,v2,a,b,p;
                  gdouble BA,SRT,L0,L1,A0,A1,A10,L10, Q,S,R, absa;

                  current = &(g_array_index (config->cage_points, GimpCagePoint, (j+1) % n_cage_vertices));
                  v1 = last->src_point;
                  v2 = current->src_point;
                  p.x = x;
                  p.y = y;
                  a.x = v2.x - v1.x;
                  a.y = v2.y - v1.y;
                  absa = gimp_vector2_length (&a);

                  b.x = v1.x - x;
                  b.y = v1.y - y;
                  Q = a.x * a.x + a.y * a.y;
                  S = b.x * b.x + b.y * b.y;
                  R = 2.0 * (a.x * b.x + a.y * b.y);
                  BA = b.x * a.y - b.y * a.x;
                  SRT = sqrt(4.0 * S * Q - R * R);

                  L0 = log(S);
                  L1 = log(S + Q + R);
                  A0 = atan2(R, SRT) / SRT;
                  A1 = atan2(2.0 * Q + R, SRT) / SRT;
                  A10 = A1 - A0;
                  L10 = L1 - L0;

                  /* edge coef */
                  coef[j + n_cage_vertices] = (-absa / (4.0 * G_PI)) * ((4.0*S-(R*R)/Q) * A10 + (R / (2.0 * Q)) * L10 + L1 - 2.0);

                  if (isnan(coef[j + n_cage_vertices]))
                    {
                      coef[j + n_cage_vertices] = 0.0;
                    }

                  /* vertice coef */
                  if (!gimp_operation_cage_coef_calc_is_on_straight (&v1, &v2, &p))
                    {
                      coef[j] += (BA / (2.0 * G_PI)) * (L10 /(2.0*Q) - A10 * (2.0 + R / Q));
                      coef[(j+1)%n_cage_vertices] -= (BA / (2.0 * G_PI)) * (L10 / (2.0 * Q) - A10 * (R / Q));
                    }

                  last = current;
                }
            }

          coef += 2 * n_cage_vertices;

          /* update x and y coordinates */
          x++;
          if (x >= (it->roi->x + it->roi->width))
            {
              x = it->roi->x;
              y++;
            }
        }
    }

  return TRUE;
}
예제 #5
0
static gint32
do_curl_effect (gint32 drawable_id)
{
  gint          x = 0;
  gint          y = 0;
  gboolean      color_image;
  gint          x1, y1, k;
  guint         alpha_pos, progress, max_progress;
  gdouble       intensity, alpha;
  GimpVector2   v, dl, dr;
  gdouble       dl_mag, dr_mag, angle, factor;
  guchar       *pp, *dest, fore_grayval, back_grayval;
  guchar       *gradsamp;
  GimpPixelRgn  dest_rgn;
  gpointer      pr;
  gint32        curl_layer_id;
  guchar       *grad_samples  = NULL;

  color_image = gimp_drawable_is_rgb (drawable_id);

  curl_layer =
    gimp_drawable_get (gimp_layer_new (image_id,
				       _("Curl Layer"),
				       true_sel_width,
				       true_sel_height,
				       color_image ?
                                       GIMP_RGBA_IMAGE : GIMP_GRAYA_IMAGE,
				       100, GIMP_NORMAL_MODE));

  curl_layer_id = curl_layer->drawable_id;

  gimp_image_insert_layer (image_id, curl_layer->drawable_id,
                           gimp_item_get_parent (drawable_id),
                           drawable_position);
  gimp_drawable_fill (curl_layer->drawable_id, GIMP_FILL_TRANSPARENT);

  gimp_drawable_offsets (drawable_id, &x1, &y1);
  gimp_layer_set_offsets (curl_layer->drawable_id, sel_x + x1, sel_y + y1);
  gimp_tile_cache_ntiles (2 * (curl_layer->width / gimp_tile_width () + 1));

  gimp_pixel_rgn_init (&dest_rgn, curl_layer,
		       0, 0, true_sel_width, true_sel_height, TRUE, TRUE);

  /* Init shade_under */
  gimp_vector2_set (&dl, -sel_width, -sel_height);
  dl_mag = gimp_vector2_length (&dl);
  gimp_vector2_set (&dr,
		    -(sel_width - right_tangent.x),
		    -(sel_height - right_tangent.y));
  dr_mag = gimp_vector2_length (&dr);
  alpha = acos (gimp_vector2_inner_product (&dl, &dr) / (dl_mag * dr_mag));

  /* Init shade_curl */

  fore_grayval = GIMP_RGB_LUMINANCE (fore_color[0],
                                     fore_color[1],
                                     fore_color[2]) + 0.5;
  back_grayval = GIMP_RGB_LUMINANCE (back_color[0],
                                     back_color[1],
                                     back_color[2]) + 0.5;

  /* Gradient Samples */
  switch (curl.colors)
    {
    case CURL_COLORS_FG_BG:
      break;
    case CURL_COLORS_GRADIENT:
      grad_samples = get_gradient_samples (curl_layer->drawable_id, FALSE);
      break;
    case CURL_COLORS_GRADIENT_REVERSE:
      grad_samples = get_gradient_samples (curl_layer->drawable_id, TRUE);
      break;
    }

  max_progress = 2 * sel_width * sel_height;
  progress = 0;

  alpha_pos = dest_rgn.bpp - 1;

  /* Main loop */
  for (pr = gimp_pixel_rgns_register (1, &dest_rgn);
       pr != NULL;
       pr = gimp_pixel_rgns_process (pr))
    {
      dest = dest_rgn.data;

      for (y1 = dest_rgn.y; y1 < dest_rgn.y + dest_rgn.h; y1++)
	{
	  pp = dest;
	  for (x1 = dest_rgn.x; x1 < dest_rgn.x + dest_rgn.w; x1++)
	    {
	      /* Map coordinates to get the curl correct... */
              switch (curl.orientation)
                {
                case CURL_ORIENTATION_VERTICAL:
		  x = CURL_EDGE_RIGHT (curl.edge) ? x1 : sel_width  - 1 - x1;
		  y = CURL_EDGE_UPPER (curl.edge) ? y1 : sel_height - 1 - y1;
                  break;

                case CURL_ORIENTATION_HORIZONTAL:
                  x = CURL_EDGE_LOWER (curl.edge) ? y1 : sel_width  - 1 - y1;
		  y = CURL_EDGE_LEFT  (curl.edge) ? x1 : sel_height - 1 - x1;
                  break;
		}

	      if (left_of_diagl (x, y))
		{ /* uncurled region */
		  for (k = 0; k <= alpha_pos; k++)
		    pp[k] = 0;
		}
	      else if (right_of_diagr (x, y) ||
		       (right_of_diagm (x, y) &&
			below_diagb (x, y) &&
			!inside_circle (x, y)))
		{
		  /* curled region */
		  for (k = 0; k <= alpha_pos; k++)
		    pp[k] = 0;
		}
	      else
		{
		  v.x = -(sel_width - x);
		  v.y = -(sel_height - y);
		  angle = acos (gimp_vector2_inner_product (&v, &dl) /
				(gimp_vector2_length (&v) * dl_mag));

		  if (inside_circle (x, y) || below_diagb (x, y))
		    {
		      /* Below the curl. */
		      factor = angle / alpha;
		      for (k = 0; k < alpha_pos; k++)
			pp[k] = 0;

		      pp[alpha_pos] = (curl.shade ?
                                       (guchar) ((float) 255 * (float) factor) :
                                       0);
		    }
		  else
		    {
		      /* On the curl */
                      switch (curl.colors)
                        {
                        case CURL_COLORS_FG_BG:
			  intensity = pow (sin (G_PI * angle / alpha), 1.5);
			  if (color_image)
			    {
			      pp[0] = (intensity * back_color[0] +
                                       (1.0 - intensity) * fore_color[0]);
			      pp[1] = (intensity * back_color[1] +
                                       (1.0 - intensity) * fore_color[1]);
			      pp[2] = (intensity * back_color[2] +
                                       (1.0 - intensity) * fore_color[2]);
			    }
			  else
			    pp[0] = (intensity * back_grayval +
                                     (1 - intensity) * fore_grayval);

			  pp[alpha_pos] = (guchar) ((double) 255.99 *
                                                    (1.0 - intensity *
                                                     (1.0 - curl.opacity)));
                          break;

                        case CURL_COLORS_GRADIENT:
                        case CURL_COLORS_GRADIENT_REVERSE:
			  /* Calculate position in Gradient */
                          intensity =
                            (angle/alpha) + sin (G_PI*2 * angle/alpha) * 0.075;

			  /* Check boundaries */
			  intensity = CLAMP (intensity, 0.0, 1.0);
			  gradsamp  = (grad_samples +
                                       ((guint) (intensity * NGRADSAMPLES)) *
                                       dest_rgn.bpp);

			  if (color_image)
			    {
			      pp[0] = gradsamp[0];
			      pp[1] = gradsamp[1];
			      pp[2] = gradsamp[2];
			    }
			  else
			    pp[0] = gradsamp[0];

			  pp[alpha_pos] =
                            (guchar) ((double) gradsamp[alpha_pos] *
                                      (1.0 - intensity * (1.0 - curl.opacity)));
                          break;
                        }
		    }
		}
	      pp += dest_rgn.bpp;
	    }
	  dest += dest_rgn.rowstride;
	}
      progress += dest_rgn.w * dest_rgn.h;
      gimp_progress_update ((double) progress / (double) max_progress);
    }

  gimp_progress_update (1.0);
  gimp_drawable_flush (curl_layer);
  gimp_drawable_merge_shadow (curl_layer->drawable_id, FALSE);
  gimp_drawable_update (curl_layer->drawable_id,
			0, 0, curl_layer->width, curl_layer->height);
  gimp_drawable_detach (curl_layer);

  g_free (grad_samples);

  return curl_layer_id;
}
예제 #6
0
static void
init_calculation (gint32 drawable_id)
{
  gdouble      k;
  gdouble      alpha, beta;
  gdouble      angle;
  GimpVector2  v1, v2;
  gint32      *image_layers;
  gint32       nlayers;
  GimpRGB      color;

  gimp_layer_add_alpha (drawable_id);

  /* Image parameters */

  /* Determine Position of original Layer in the Layer stack. */

  image_layers = gimp_image_get_layers (image_id, &nlayers);
  drawable_position = 0;
  while (drawable_position < nlayers &&
	 image_layers[drawable_position] != drawable_id)
    drawable_position++;

  switch (curl.orientation)
    {
    case CURL_ORIENTATION_VERTICAL:
      sel_width  = true_sel_width;
      sel_height = true_sel_height;
      break;

    case CURL_ORIENTATION_HORIZONTAL:
      sel_width  = true_sel_height;
      sel_height = true_sel_width;
      break;
    }

  /* Circle parameters */

  alpha = atan ((double) sel_height / sel_width);
  beta = alpha / 2.0;
  k = sel_width / ((G_PI + alpha) * sin (beta) + cos (beta));
  gimp_vector2_set (&center, k * cos (beta), k * sin (beta));
  radius = center.y;

  /* left_tangent  */

  gimp_vector2_set (&left_tangent, radius * -sin (alpha), radius * cos (alpha));
  gimp_vector2_add (&left_tangent, &left_tangent, &center);

  /* right_tangent */

  gimp_vector2_sub (&v1, &left_tangent, &center);
  gimp_vector2_set (&v2, sel_width - center.x, sel_height - center.y);
  angle = -2.0 * acos (gimp_vector2_inner_product (&v1, &v2) /
		       (gimp_vector2_length (&v1) *
                        gimp_vector2_length (&v2)));
  gimp_vector2_set (&right_tangent,
		    v1.x * cos (angle) + v1.y * -sin (angle),
		    v1.x * sin (angle) + v1.y * cos (angle));
  gimp_vector2_add (&right_tangent, &right_tangent, &center);

  /* Slopes */

  diagl_slope = (double) sel_width / sel_height;
  diagr_slope = (sel_width - right_tangent.x) / (sel_height - right_tangent.y);
  diagb_slope = ((right_tangent.y - left_tangent.y) /
                 (right_tangent.x - left_tangent.x));
  diagm_slope = (sel_width - center.x) / sel_height;

  /* Colors */

  gimp_context_get_foreground (&color);
  gimp_rgb_get_uchar (&color, &fore_color[0], &fore_color[1], &fore_color[2]);

  gimp_context_get_background (&color);
  gimp_rgb_get_uchar (&color, &back_color[0], &back_color[1], &back_color[2]);
}