Example #1
0
static void
update_vector_prev (void)
{
  static gint    ok = 0;
  gint           i, x, y;
  gdouble        dir, xo, yo;
  gdouble        val;
  static gdouble last_val = 0.0;
  guchar         gray[3]  = {120, 120, 120};
  guchar         red[3]   = {255, 0, 0};
  guchar         white[3] = {255, 255, 255};

  if (vector_preview_brightness_adjust)
    val = 1.0 - gtk_adjustment_get_value (GTK_ADJUSTMENT (vector_preview_brightness_adjust)) / 100.0;
  else
    val = 0.5;

  if (!ok || (val != last_val))
    {
      infile_copy_to_ppm (&update_vector_preview_backup);
      ppm_apply_brightness (&update_vector_preview_backup, val, 1,1,1);

      if ((update_vector_preview_backup.width != OMWIDTH) ||
          (update_vector_preview_backup.height != OMHEIGHT))
        resize_fast (&update_vector_preview_backup, OMWIDTH, OMHEIGHT);
      ok = 1;
    }
  ppm_copy (&update_vector_preview_backup, &update_vector_preview_buffer);

  for (i = 0; i < num_vectors; i++)
    {
      gdouble s;

      x = vector[i].x * OMWIDTH;
      y = vector[i].y * OMHEIGHT;
      dir = gimp_deg_to_rad (vector[i].dir);
      s = gimp_deg_to_rad (vector[i].str);
      xo = sin (dir) * (6.0+100*s);
      yo = cos (dir) * (6.0+100*s);

      if (i == selectedvector)
        {
          ppm_drawline (&update_vector_preview_buffer,
                        x - xo, y - yo, x + xo, y + yo, red);
        }
      else
        {
          ppm_drawline (&update_vector_preview_buffer,
                        x - xo, y - yo, x + xo, y + yo, gray);
        }
      ppm_put_rgb (&update_vector_preview_buffer, x - xo, y - yo, white);
  }

  gimp_preview_area_draw (GIMP_PREVIEW_AREA (vector_preview),
                          0, 0, OMWIDTH, OMHEIGHT,
                          GIMP_RGB_IMAGE,
                          (guchar *)update_vector_preview_buffer.col,
                          OMWIDTH * 3);
}
Example #2
0
static void
angle_adjust_move_callback (GtkWidget *w, gpointer data)
{
  if (adjignore)
    return;
  vector[selectedvector].dir = gtk_adjustment_get_value (GTK_ADJUSTMENT (angle_adjust));
  vector[selectedvector].dx =
    sin (gimp_deg_to_rad (vector[selectedvector].dir));
  vector[selectedvector].dy =
    cos (gimp_deg_to_rad (vector[selectedvector].dir));
  update_vector_prev ();
  update_orient_map_preview_prev ();
}
Example #3
0
static void
add_new_vector (gdouble x, gdouble y)
{
  vector[num_vectors].x = x;
  vector[num_vectors].y = y;
  vector[num_vectors].dir = 0.0;
  vector[num_vectors].dx = sin (gimp_deg_to_rad (0.0));
  vector[num_vectors].dy = cos (gimp_deg_to_rad (0.0));
  vector[num_vectors].str = 1.0;
  vector[num_vectors].type = 0;
  selectedvector = num_vectors;
  num_vectors++;
}
Example #4
0
static void
update_orient_map_preview_prev (void)
{
  int    x, y;
  guchar black[3] = {0, 0, 0};
  guchar gray[3] = {120, 120, 120};
  guchar white[3] = {255, 255, 255};

  if (!PPM_IS_INITED (&update_om_preview_nbuffer))
    ppm_new (&update_om_preview_nbuffer,OMWIDTH,OMHEIGHT);

  fill (&update_om_preview_nbuffer, black);

  for (y = 6; y < OMHEIGHT-4; y += 10)
    for (x = 6; x < OMWIDTH-4; x += 10)
      {
        double dir =
          gimp_deg_to_rad (get_direction (x / (double)OMWIDTH,
                                          y / (double)OMHEIGHT,0));
        double xo = sin (dir) * 4.0;
        double yo = cos (dir) * 4.0;
        ppm_drawline (&update_om_preview_nbuffer,
                      x - xo, y - yo, x + xo, y + yo,
                      gray);
        ppm_put_rgb (&update_om_preview_nbuffer,
                     x - xo, y - yo,
                     white);
      }

  gimp_preview_area_draw (GIMP_PREVIEW_AREA (orient_map_preview_prev),
                          0, 0, OMWIDTH, OMHEIGHT,
                          GIMP_RGB_IMAGE,
                          (guchar *)update_om_preview_nbuffer.col,
                          OMWIDTH * 3);

  gtk_widget_queue_draw (orient_map_preview_prev);

  gtk_widget_set_sensitive (prev_button, (num_vectors > 1));
  gtk_widget_set_sensitive (next_button, (num_vectors > 1));
  gtk_widget_set_sensitive (add_button, (num_vectors < MAXORIENTVECT));
  gtk_widget_set_sensitive (kill_button, (num_vectors > 1));
}
Example #5
0
static void
rotate_angle_changed (GtkAdjustment     *adj,
                      GimpTransformTool *tr_tool)
{
  gdouble value = gimp_deg_to_rad (gtk_adjustment_get_value (adj));

#define ANGLE_EPSILON 0.0001

  if (ABS (value - tr_tool->trans_info[ANGLE]) > ANGLE_EPSILON)
    {
      gimp_draw_tool_pause (GIMP_DRAW_TOOL (tr_tool));

      tr_tool->trans_info[REAL_ANGLE] = tr_tool->trans_info[ANGLE] = value;

      gimp_transform_tool_push_internal_undo (tr_tool);

      gimp_transform_tool_recalc_matrix (tr_tool);

      gimp_draw_tool_resume (GIMP_DRAW_TOOL (tr_tool));
    }

#undef ANGLE_EPSILON
}
Example #6
0
static void
mblur_radial (GimpDrawable *drawable,
              GimpPreview  *preview,
              gint          x1,
              gint          y1,
              gint          width,
              gint          height)
{
  GimpPixelRgn      dest_rgn;
  GimpPixelFetcher *pft;
  gpointer          pr;
  GimpRGB           background;

  gdouble   center_x;
  gdouble   center_y;
  guchar   *dest;
  guchar   *d;
  guchar    pixel[4];
  guchar    p1[4], p2[4], p3[4], p4[4];
  gint32    sum[4];

  gint      progress, max_progress, c;

  gint      x, y, i, p, n, count;
  gdouble   angle, theta, r, xx, yy, xr, yr;
  gdouble   phi, phi_start, s_val, c_val;
  gdouble   dx, dy;

  /* initialize */

  xx = 0.0;
  yy = 0.0;

  center_x = mbvals.center_x;
  center_y = mbvals.center_y;

  gimp_pixel_rgn_init (&dest_rgn, drawable,
                       x1, y1, width, height, (preview == NULL), TRUE);

  pft = gimp_pixel_fetcher_new (drawable, FALSE);

  gimp_context_get_background (&background);
  gimp_pixel_fetcher_set_bg_color (pft, &background);

  progress     = 0;
  max_progress = width * height;

  angle = gimp_deg_to_rad (mbvals.angle);

  for (pr = gimp_pixel_rgns_register (1, &dest_rgn), p = 0;
       pr != NULL;
       pr = gimp_pixel_rgns_process (pr), p++)
    {
      dest = dest_rgn.data;

      for (y = dest_rgn.y; y < dest_rgn.y + dest_rgn.h; y++)
        {
          d = dest;

          for (x = dest_rgn.x; x < dest_rgn.x + dest_rgn.w; x++)
            {
              xr = (gdouble) x - center_x;
              yr = (gdouble) y - center_y;

              r = sqrt (SQR (xr) + SQR (yr));
              n = r * angle;

              if (angle == 0.0)
                {
                  gimp_pixel_fetcher_get_pixel (pft, x, y, d);
                  d += dest_rgn.bpp;
                  continue;
                }

              /* ensure quality with small angles */
              if (n < 3)
                n = 3;  /* always use at least 3 (interpolation) steps */

              /* limit loop count due to performanc reasons */
              if (n > 100)
                n = 100 + sqrt (n-100);

              if (xr != 0.0)
                {
                  phi = atan(yr/xr);
                  if (xr < 0.0)
                    phi = G_PI + phi;

                }
              else
                {
                  if (yr >= 0.0)
                    phi = G_PI_2;
                  else
                    phi = -G_PI_2;
                }

              for (c = 0; c < img_bpp; c++)
                sum[c] = 0;

              if (n == 1)
                phi_start = phi;
              else
                phi_start = phi + angle/2.0;

              theta = angle / (gdouble)n;
              count = 0;

              for (i = 0; i < n; i++)
                {
                  s_val = sin (phi_start - (gdouble) i * theta);
                  c_val = cos (phi_start - (gdouble) i * theta);

                  xx = center_x + r * c_val;
                  yy = center_y + r * s_val;

                  if ((yy < y1) || (yy >= y1 + height) ||
                      (xx < x1) || (xx >= x1 + width))
                    continue;

                  ++count;
                  if ((xx + 1 < x1 + width) && (yy + 1 < y1 + height))
                    {
                      dx = xx - floor (xx);
                      dy = yy - floor (yy);

                      gimp_pixel_fetcher_get_pixel (pft, xx,   yy,   p1);
                      gimp_pixel_fetcher_get_pixel (pft, xx+1, yy,   p2);
                      gimp_pixel_fetcher_get_pixel (pft, xx,   yy+1, p3);
                      gimp_pixel_fetcher_get_pixel (pft, xx+1, yy+1, p4);

                      for (c = 0; c < img_bpp; c++)
                        {
                          pixel[c] = (((gdouble) p1[c] * (1.0-dx) +
                                       (gdouble) p2[c] * dx) * (1.0-dy) +
                                      ((gdouble) p3[c] * (1.0-dx) +
                                       (gdouble) p4[c] * dx) * dy);
                        }
                    }
                  else
                    {
                      gimp_pixel_fetcher_get_pixel (pft, xx+.5, yy+.5, pixel);
                    }

                  if (has_alpha)
                    {
                      gint32 alpha = pixel[img_bpp-1];

                      sum[img_bpp-1] += alpha;

                      for (c = 0; c < img_bpp-1; c++)
                        sum[c] += pixel[c] * alpha;
                    }
                  else
                    {
                      for (c = 0; c < img_bpp; c++)
                        sum[c] += pixel[c];
                    }
                }

              if (count == 0)
                {
                  gimp_pixel_fetcher_get_pixel (pft, xx, yy, d);
                }
              else
                {
                  if (has_alpha)
                    {
                      gint32 alpha = sum[img_bpp-1];

                      if ((d[img_bpp-1] = alpha/count) != 0)
                        {
                          for (c = 0; c < img_bpp-1; c++)
                            d[c] = sum[c] / alpha;
                        }
                    }
                  else
                    {
                      for (c = 0; c < img_bpp; c++)
                        d[c] = sum[c] / count;
                    }
                }

              d += dest_rgn.bpp;
            }

          dest += dest_rgn.rowstride;
        }

      if (preview)
        {
          gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview),
                                             &dest_rgn);
        }
      else
        {
          progress += dest_rgn.w * dest_rgn.h;

          if ((p % 8) == 0)
            gimp_progress_update ((gdouble) progress / max_progress);
        }
    }

  gimp_pixel_fetcher_destroy (pft);

}
Example #7
0
static void
gimp_brush_generated_dirty (GimpBrushGenerated *brush)
{
  gint                x, y;
  guchar             *centerp;
  double             d;
  double             exponent;
  guchar              a;
  gint                length;
  gint                width  = 0;
  gint                height = 0;
  guchar             *lookup;
  double             sum;
  double             c, s, cs, ss;
  double             short_radius;
  double             buffer[OVERSAMPLING];

  s = sin (gimp_deg_to_rad (brush->angle));
  c = cos (gimp_deg_to_rad (brush->angle));

  short_radius = brush->radius / brush->aspect_ratio;

  brush->x_axis.x =        c * brush->radius;
  brush->x_axis.y = -1.0 * s * brush->radius;
  brush->y_axis.x =        s * short_radius;
  brush->y_axis.y =        c * short_radius;

  switch (brush->shape)
    {
    case BRUSH_SHAPE_CIRCLE:
      width  = static_cast<int>(ceil (sqrt (brush->x_axis.x * brush->x_axis.x +
                                            brush->y_axis.x * brush->y_axis.x)));
      height = static_cast<int>(ceil (sqrt (brush->x_axis.y * brush->x_axis.y +
                                            brush->y_axis.y * brush->y_axis.y)));
      break;

    case BRUSH_SHAPE_SQUARE:
      width  = static_cast<int>(ceil (fabs (brush->x_axis.x) + fabs (brush->y_axis.x)));
      height = static_cast<int>(ceil (fabs (brush->x_axis.y) + fabs (brush->y_axis.y)));
      break;

    case BRUSH_SHAPE_DIAMOND:
      width  = static_cast<int>(ceil (std::max(fabs (brush->x_axis.x), fabs (brush->y_axis.x))));
      height = static_cast<int>(ceil (std::max(fabs (brush->x_axis.y), fabs (brush->y_axis.y))));
      break;

    default:
      return;
    }

  if (brush->spikes > 2)
    {
      /* could be optimized by respecting the angle */
      width = height = static_cast<int>(ceil (sqrt (brush->radius * brush->radius +
                                                    short_radius * short_radius)));
      brush->y_axis.x =        s * brush->radius;
      brush->y_axis.y =        c * brush->radius;
    }

  brush->mask = new GrayscaleBuffer(width  * 2 + 1,
                                    height * 2 + 1,
                                    0);

  centerp = brush->mask->get_data() + height * brush->mask->get_width() + width;

  /* set up lookup table */
  length = static_cast<int>(OVERSAMPLING * ceil (1 + sqrt (2 *
                                                           ceil (brush->radius + 1.0) *
                                                           ceil (brush->radius + 1.0))));

  if ((1.0 - brush->hardness) < 0.0000004)
    exponent = 1000000.0;
  else
    exponent = 0.4 / (1.0 - brush->hardness);

  lookup = new guchar[length];
  sum = 0.0;

  for (x = 0; x < OVERSAMPLING; x++)
    {
      d = fabs ((x + 0.5) / OVERSAMPLING - 0.5);

      if (d > brush->radius)
        buffer[x] = 0.0;
      else
        buffer[x] = gauss (pow (d / brush->radius, exponent));

      sum += buffer[x];
    }

  for (x = 0; d < brush->radius || sum > 0.00001; d += 1.0 / OVERSAMPLING)
    {
      sum -= buffer[x % OVERSAMPLING];

      if (d > brush->radius)
        buffer[x % OVERSAMPLING] = 0.0;
      else
        buffer[x % OVERSAMPLING] = gauss (pow (d / brush->radius, exponent));

      sum += buffer[x % OVERSAMPLING];
      lookup[x++] = static_cast<int>(rint(sum * (255.0 / OVERSAMPLING)));
    }

  while (x < length)
    {
      lookup[x++] = 0;
    }

  cs = cos (- 2 * M_PI / brush->spikes);
  ss = sin (- 2 * M_PI / brush->spikes);

  /* for an even number of spikes compute one half and mirror it */
  for (y = (brush->spikes % 2 ? -height : 0); y <= height; y++)
    {
      for (x = -width; x <= width; x++)
        {
          double tx, ty, angle;

          tx = c*x - s*y;
          ty = fabs (s*x + c*y);

          if (brush->spikes > 2)
            {
              angle = atan2 (ty, tx);

              while (angle > M_PI / brush->spikes)
                {
                  double sx = tx, sy = ty;

                  tx = cs * sx - ss * sy;
                  ty = ss * sx + cs * sy;

                  angle -= 2 * M_PI / brush->spikes;
                }
            }

          ty *= brush->aspect_ratio;
          switch (brush->shape)
            {
            case BRUSH_SHAPE_CIRCLE:
              d = sqrt (tx*tx + ty*ty);
              break;
            case BRUSH_SHAPE_SQUARE:
              d = std::max (fabs (tx), fabs (ty));
              break;
            case BRUSH_SHAPE_DIAMOND:
              d = fabs (tx) + fabs (ty);
              break;
            }

          if (d < brush->radius + 1)
            a = lookup[(gint) rint (d * OVERSAMPLING)];
          else
            a = 0;

          centerp[ y * brush->mask->get_width() + x] = a;

          if (brush->spikes % 2 == 0)
            centerp[-1 * y * brush->mask->get_width() - x] = a;
        }
    }

  delete lookup;
}
Example #8
0
static GimpBlob *
ink_pen_ellipse (GimpInkOptions *options,
                 gdouble         x_center,
                 gdouble         y_center,
                 gdouble         pressure,
                 gdouble         xtilt,
                 gdouble         ytilt,
                 gdouble         velocity)
{
  GimpBlobFunc blob_function;
  gdouble      size;
  gdouble      tsin, tcos;
  gdouble      aspect, radmin;
  gdouble      x,y;
  gdouble      tscale;
  gdouble      tscale_c;
  gdouble      tscale_s;

  /* Adjust the size depending on pressure. */

  size = options->size * (1.0 + options->size_sensitivity *
                          (2.0 * pressure - 1.0));

  /* Adjust the size further depending on pointer velocity and
   * velocity-sensitivity.  These 'magic constants' are 'feels
   * natural' tigert-approved. --ADM
   */

  if (velocity < 3.0)
    velocity = 3.0;

#ifdef VERBOSE
  g_printerr ("%g (%g) -> ", size, velocity);
#endif

  size = (options->vel_sensitivity *
          ((4.5 * size) / (1.0 + options->vel_sensitivity * (2.0 * velocity)))
          + (1.0 - options->vel_sensitivity) * size);

#ifdef VERBOSE
  g_printerr ("%g\n", (gfloat) size);
#endif

  /* Clamp resulting size to sane limits */

  if (size > options->size * (1.0 + options->size_sensitivity))
    size = options->size * (1.0 + options->size_sensitivity);

  if (size * SUBSAMPLE < 1.0)
    size = 1.0 / SUBSAMPLE;

  /* Add brush angle/aspect to tilt vectorially */

  /* I'm not happy with the way the brush widget info is combined with
   * tilt info from the brush. My personal feeling is that
   * representing both as affine transforms would make the most
   * sense. -RLL
   */

  tscale   = options->tilt_sensitivity * 10.0;
  tscale_c = tscale * cos (gimp_deg_to_rad (options->tilt_angle));
  tscale_s = tscale * sin (gimp_deg_to_rad (options->tilt_angle));

  x = (options->blob_aspect * cos (options->blob_angle) +
       xtilt * tscale_c - ytilt * tscale_s);
  y = (options->blob_aspect * sin (options->blob_angle) +
       ytilt * tscale_c + xtilt * tscale_s);

#ifdef VERBOSE
  g_printerr ("angle %g aspect %g; %g %g; %g %g\n",
              options->blob_angle, options->blob_aspect,
              tscale_c, tscale_s, x, y);
#endif

  aspect = sqrt (SQR (x) + SQR (y));

  if (aspect != 0)
    {
      tcos = x / aspect;
      tsin = y / aspect;
    }
  else
    {
      tsin = sin (options->blob_angle);
      tcos = cos (options->blob_angle);
    }

  aspect = CLAMP (aspect, 1.0, 10.0);

  radmin = MAX (1.0, SUBSAMPLE * size / aspect);

  switch (options->blob_type)
    {
    case GIMP_INK_BLOB_TYPE_CIRCLE:
      blob_function = gimp_blob_ellipse;
      break;

    case GIMP_INK_BLOB_TYPE_SQUARE:
      blob_function = gimp_blob_square;
      break;

    case GIMP_INK_BLOB_TYPE_DIAMOND:
      blob_function = gimp_blob_diamond;
      break;

    default:
      g_return_val_if_reached (NULL);
      break;
    }

  return (* blob_function) (x_center * SUBSAMPLE,
                            y_center * SUBSAMPLE,
                            radmin * aspect * tcos,
                            radmin * aspect * tsin,
                            -radmin * tsin,
                            radmin * tcos);
}
Example #9
0
/* This function is shared between gimp_brush_generated_scale_size and
 * gimp_brush_generated_calc, therefore we provide a bunch of optional
 * pointers for returnvalues.
 */
static void
gimp_brush_generated_get_half_size (GimpBrushGenerated      *gbrush,
                                    GimpBrushGeneratedShape  shape,
                                    gfloat                   radius,
                                    gint                     spikes,
                                    gfloat                   hardness,
                                    gfloat                   aspect_ratio,
                                    gdouble                  angle_in_degrees,
                                    gint                    *half_width,
                                    gint                    *half_height,
                                    gdouble                 *_s,
                                    gdouble                 *_c,
                                    GimpVector2             *_x_axis,
                                    GimpVector2             *_y_axis)
{
  gdouble      c, s;
  gdouble      short_radius;
  GimpVector2  x_axis;
  GimpVector2  y_axis;

  s = sin (gimp_deg_to_rad (angle_in_degrees));
  c = cos (gimp_deg_to_rad (angle_in_degrees));

  short_radius = radius / aspect_ratio;

  x_axis.x =        c * radius;
  x_axis.y = -1.0 * s * radius;
  y_axis.x =        s * short_radius;
  y_axis.y =        c * short_radius;

  switch (shape)
    {
    case GIMP_BRUSH_GENERATED_CIRCLE:
      *half_width  = ceil (sqrt (x_axis.x * x_axis.x + y_axis.x * y_axis.x));
      *half_height = ceil (sqrt (x_axis.y * x_axis.y + y_axis.y * y_axis.y));
      break;

    case GIMP_BRUSH_GENERATED_SQUARE:
      *half_width  = ceil (fabs (x_axis.x) + fabs (y_axis.x));
      *half_height = ceil (fabs (x_axis.y) + fabs (y_axis.y));
      break;

    case GIMP_BRUSH_GENERATED_DIAMOND:
      *half_width  = ceil (MAX (fabs (x_axis.x), fabs (y_axis.x)));
      *half_height = ceil (MAX (fabs (x_axis.y), fabs (y_axis.y)));
      break;
    }

  if (spikes > 2)
    {
      /* could be optimized by respecting the angle */
      *half_width = *half_height = ceil (sqrt (radius * radius +
                                               short_radius * short_radius));
      y_axis.x = s * radius;
      y_axis.y = c * radius;
    }

  /*  These will typically be set then this function is called by
   *  gimp_brush_generated_calc, which needs the values in its algorithms.
   */
  if (_s != NULL)
    *_s = s;

  if (_c != NULL)
    *_c = c;

  if (_x_axis != NULL)
    *_x_axis = x_axis;

  if (_y_axis != NULL)
    *_y_axis = y_axis;
}
Example #10
0
static void
draw_wireframe_sphere (gint startx,
		       gint starty,
		       gint pw,
		       gint ph)
{
  GimpVector3 p[2 * (WIRESIZE + 5)];
  gint        cnt, cnt2, n = 0;
  gdouble     x1, y1, x2, y2, twopifac, cx1, cy1, cx2, cy2;

  /* Compute wireframe points */
  /* ======================== */

  twopifac = (2.0 * G_PI) / WIRESIZE;

  for (cnt = 0; cnt < WIRESIZE; cnt++)
    {
      p[cnt].x = mapvals.radius * cos ((gdouble) cnt * twopifac);
      p[cnt].y = 0.0;
      p[cnt].z = mapvals.radius * sin ((gdouble) cnt * twopifac);
      gimp_vector3_rotate (&p[cnt],
			   gimp_deg_to_rad (mapvals.alpha),
			   gimp_deg_to_rad (mapvals.beta),
			   gimp_deg_to_rad (mapvals.gamma));
      gimp_vector3_add (&p[cnt], &p[cnt], &mapvals.position);
    }

  p[cnt] = p[0];

  for (cnt = WIRESIZE + 1; cnt < 2 * WIRESIZE + 1; cnt++)
    {
      p[cnt].x = mapvals.radius * cos ((gdouble) (cnt-(WIRESIZE+1))*twopifac);
      p[cnt].y = mapvals.radius * sin ((gdouble) (cnt-(WIRESIZE+1))*twopifac);
      p[cnt].z = 0.0;
      gimp_vector3_rotate (&p[cnt],
			   gimp_deg_to_rad (mapvals.alpha),
			   gimp_deg_to_rad (mapvals.beta),
			   gimp_deg_to_rad (mapvals.gamma));
      gimp_vector3_add (&p[cnt], &p[cnt], &mapvals.position);
    }

  p[cnt] = p[WIRESIZE+1];
  cnt++;
  cnt2 = cnt;

  /* Find rotated axis */
  /* ================= */

  gimp_vector3_set (&p[cnt], 0.0, -0.35, 0.0);
  gimp_vector3_rotate (&p[cnt],
		       gimp_deg_to_rad (mapvals.alpha),
		       gimp_deg_to_rad (mapvals.beta),
		       gimp_deg_to_rad (mapvals.gamma));
  p[cnt+1] = mapvals.position;

  gimp_vector3_set (&p[cnt+2], 0.0, 0.0, -0.35);
  gimp_vector3_rotate (&p[cnt+2],
		       gimp_deg_to_rad (mapvals.alpha),
		       gimp_deg_to_rad (mapvals.beta),
		       gimp_deg_to_rad (mapvals.gamma));
  p[cnt+3] = mapvals.position;

  p[cnt + 4] = p[cnt];
  gimp_vector3_mul (&p[cnt + 4], -1.0);
  p[cnt + 5] = p[cnt + 1];

  gimp_vector3_add (&p[cnt],     &p[cnt],     &mapvals.position);
  gimp_vector3_add (&p[cnt + 2], &p[cnt + 2], &mapvals.position);
  gimp_vector3_add (&p[cnt + 4], &p[cnt + 4], &mapvals.position);

  /* Draw the circles (equator and zero meridian) */
  /* ============================================ */

  cx1 = (gdouble) startx;
  cy1 = (gdouble) starty;
  cx2 = cx1 + (gdouble) pw;
  cy2 = cy1 + (gdouble) ph;

  for (cnt = 0; cnt < cnt2 - 1; cnt++)
    {
      if (p[cnt].z > mapvals.position.z && p[cnt + 1].z > mapvals.position.z)
        {
          gimp_vector_3d_to_2d (startx, starty, pw, ph,
				&x1, &y1, &mapvals.viewpoint, &p[cnt]);
          gimp_vector_3d_to_2d (startx, starty, pw, ph,
				&x2, &y2, &mapvals.viewpoint, &p[cnt + 1]);

          if (clip_line (&x1, &y1, &x2, &y2, cx1, cy1, cx2, cy2) == TRUE)
            {
              linetab[n].x1 = (gint) (x1 + 0.5);
              linetab[n].y1 = (gint) (y1 + 0.5);
              linetab[n].x2 = (gint) (x2 + 0.5);
              linetab[n].y2 = (gint) (y2 + 0.5);
              linetab[n].linewidth = 3;
              linetab[n].linestyle = GDK_LINE_SOLID;
              gdk_gc_set_line_attributes (gc,
					  linetab[n].linewidth,
					  linetab[n].linestyle,
					  GDK_CAP_NOT_LAST,
					  GDK_JOIN_MITER);
              gdk_draw_line (previewarea->window, gc,
			     linetab[n].x1, linetab[n].y1,
			     linetab[n].x2, linetab[n].y2);
              n++;
            }
        }
    }

  /* Draw the axis (pole to pole and center to zero meridian) */
  /* ======================================================== */

  for (cnt = 0; cnt < 3; cnt++)
    {
      gimp_vector_3d_to_2d (startx, starty, pw, ph,
			    &x1, &y1, &mapvals.viewpoint, &p[cnt2]);
      gimp_vector_3d_to_2d (startx, starty, pw, ph,
			    &x2, &y2, &mapvals.viewpoint, &p[cnt2 + 1]);

      if (clip_line (&x1, &y1, &x2, &y2, cx1, cy1, cx2, cy2) == TRUE)
        {
          linetab[n].x1 = RINT (x1);
          linetab[n].y1 = RINT (y1);
          linetab[n].x2 = RINT (x2);
          linetab[n].y2 = RINT (y2);

          if (p[cnt2].z < mapvals.position.z || p[cnt2+1].z < mapvals.position.z)
            {
              linetab[n].linewidth = 1;
              linetab[n].linestyle = GDK_LINE_DOUBLE_DASH;
            }
          else
            {
              linetab[n].linewidth = 3;
              linetab[n].linestyle = GDK_LINE_SOLID;
            }

          gdk_gc_set_line_attributes (gc,
				      linetab[n].linewidth,
				      linetab[n].linestyle,
				      GDK_CAP_NOT_LAST,
				      GDK_JOIN_MITER);
          gdk_draw_line (previewarea->window, gc,
			 linetab[n].x1, linetab[n].y1,
			 linetab[n].x2, linetab[n].y2);
          n++;
        }

      cnt2 += 2;
    }

  /* Mark end of lines */
  /* ================= */

  linetab[n].x1 = -1;
}
Example #11
0
static void
draw_wireframe_plane (gint startx,
		      gint starty,
		      gint pw,
		      gint ph)
{
  GimpVector3 v1, v2, a, b, c, d, dir1, dir2;
  gint        cnt, n = 0;
  gdouble     x1, y1, x2, y2, cx1, cy1, cx2, cy2, fac;

  /* Find rotated box corners */
  /* ======================== */

  gimp_vector3_set (&v1, 0.5, 0.0, 0.0);
  gimp_vector3_set (&v2, 0.0, 0.5, 0.0);

  gimp_vector3_rotate (&v1,
		       gimp_deg_to_rad (mapvals.alpha),
		       gimp_deg_to_rad (mapvals.beta),
		       gimp_deg_to_rad (mapvals.gamma));

  gimp_vector3_rotate (&v2,
		       gimp_deg_to_rad (mapvals.alpha),
		       gimp_deg_to_rad (mapvals.beta),
		       gimp_deg_to_rad (mapvals.gamma));

  dir1 = v1; gimp_vector3_normalize (&dir1);
  dir2 = v2; gimp_vector3_normalize (&dir2);

  fac = 1.0 / (gdouble) WIRESIZE;

  gimp_vector3_mul (&dir1, fac);
  gimp_vector3_mul (&dir2, fac);

  gimp_vector3_add (&a, &mapvals.position, &v1);
  gimp_vector3_sub (&b, &a, &v2);
  gimp_vector3_add (&a, &a, &v2);
  gimp_vector3_sub (&d, &mapvals.position, &v1);
  gimp_vector3_sub (&d, &d, &v2);

  c = b;

  cx1 = (gdouble) startx;
  cy1 = (gdouble) starty;
  cx2 = cx1 + (gdouble) pw;
  cy2 = cy1 + (gdouble) ph;

  for (cnt = 0; cnt <= WIRESIZE; cnt++)
    {
      gimp_vector_3d_to_2d (startx, starty, pw, ph,
			    &x1, &y1, &mapvals.viewpoint, &a);
      gimp_vector_3d_to_2d (startx, starty, pw, ph,
			    &x2, &y2, &mapvals.viewpoint, &b);

      if (clip_line (&x1, &y1, &x2, &y2, cx1, cy1, cx2, cy2) == TRUE)
        {
          linetab[n].x1 = RINT (x1);
          linetab[n].y1 = RINT (y1);
          linetab[n].x2 = RINT (x2);
          linetab[n].y2 = RINT (y2);
          linetab[n].linewidth = 1;
          linetab[n].linestyle = GDK_LINE_SOLID;
          gdk_gc_set_line_attributes (gc,
				      linetab[n].linewidth,
				      linetab[n].linestyle,
				      GDK_CAP_NOT_LAST,
				      GDK_JOIN_MITER);
          gdk_draw_line (previewarea->window, gc,
			 linetab[n].x1, linetab[n].y1,
			 linetab[n].x2, linetab[n].y2);
          n++;
        }

      gimp_vector_3d_to_2d (startx, starty, pw, ph,
			    &x1, &y1, &mapvals.viewpoint, &c);
      gimp_vector_3d_to_2d (startx, starty, pw, ph,
			    &x2, &y2, &mapvals.viewpoint, &d);

      if (clip_line (&x1, &y1, &x2, &y2, cx1, cy1, cx2, cy2) == TRUE)
        {
          linetab[n].x1 = RINT (x1);
          linetab[n].y1 = RINT (y1);
          linetab[n].x2 = RINT (x2);
          linetab[n].y2 = RINT (y2);
          linetab[n].linewidth = 1;
          linetab[n].linestyle = GDK_LINE_SOLID;
          gdk_gc_set_line_attributes (gc,
				      linetab[n].linewidth,
				      linetab[n].linestyle,
				      GDK_CAP_NOT_LAST,
				      GDK_JOIN_MITER);
          gdk_draw_line (previewarea->window, gc,
			 linetab[n].x1, linetab[n].y1,
			 linetab[n].x2, linetab[n].y2);
          n++;
        }

      gimp_vector3_sub (&a, &a, &dir1);
      gimp_vector3_sub (&b, &b, &dir1);
      gimp_vector3_add (&c, &c, &dir2);
      gimp_vector3_add (&d, &d, &dir2);
    }

  /* Mark end of lines */
  /* ================= */

  linetab[n].x1 = -1;
}
Example #12
0
/* ---------------------------------
 * gap_colordiff_LabDeltaE2000
 * ---------------------------------
 * uses algortihm found at http://colormine.org/delta-e-calculator/cie2000
 * based on L*a*b Colorspace.
 * returns deltaE scaled down to a range of 0.0 to 1.0
 */
gdouble gap_colordiff_LabDeltaE2000(guchar *aPixelPtr
                   , guchar *bPixelPtr
                   , gboolean debugPrint
                   )
{
  //Set weighting factors to 1
  gdouble k_L = 1.0;
  gdouble k_C = 1.0;
  gdouble k_H = 1.0;


  GapColorLAB lab1;
  GapColorLAB lab2;
  
  //Change Color Space to L*a*b:
  p_convert_rgb8_to_Lab(aPixelPtr, &lab1);
  p_convert_rgb8_to_Lab(bPixelPtr, &lab2);
  

  //Calculate Cprime1, Cprime2, Cabbar
  gdouble c_star_1_ab = sqrt(lab1.A * lab1.A + lab1.B * lab1.B);
  gdouble c_star_2_ab = sqrt(lab2.A * lab2.A + lab2.B * lab2.B);
  gdouble c_star_average_ab = (c_star_1_ab + c_star_2_ab) / 2;

  gdouble c_star_average_ab_pot7 = c_star_average_ab * c_star_average_ab * c_star_average_ab;
  c_star_average_ab_pot7 *= c_star_average_ab_pot7 * c_star_average_ab;

  gdouble G = 0.5 * (1 - sqrt(c_star_average_ab_pot7 / (c_star_average_ab_pot7 + 6103515625))); //25^7
  gdouble a1_prime = (1 + G) * lab1.A;
  gdouble a2_prime = (1 + G) * lab2.A;

  gdouble C_prime_1 = sqrt(a1_prime * a1_prime + lab1.B * lab1.B);
  gdouble C_prime_2 = sqrt(a2_prime * a2_prime + lab2.B * lab2.B);
  //Angles in Degree.
  gdouble h_prime_1 = (int)rint(gimp_rad_to_deg(atan2(lab1.B, a1_prime)) + 360) % 360;
  gdouble h_prime_2 = (int)rint(gimp_rad_to_deg(atan2(lab2.B, a2_prime)) + 360) % 360;

  gdouble delta_L_prime = lab2.L - lab1.L;
  gdouble delta_C_prime = C_prime_2 - C_prime_1;

  gdouble h_bar = abs(h_prime_1 - h_prime_2);
  gdouble delta_h_prime;
  if (C_prime_1 * C_prime_2 == 0) delta_h_prime = 0;
  else
  {
      if (h_bar <= 180.0)
      {
          delta_h_prime = h_prime_2 - h_prime_1;
      }
      else if (h_bar > 180.0 && h_prime_2 <= h_prime_1)
      {
          delta_h_prime = h_prime_2 - h_prime_1 + 360.0;
      }
      else
      {
          delta_h_prime = h_prime_2 - h_prime_1 - 360.0;
      }
  }
  gdouble delta_H_prime = 2 * sqrt(C_prime_1 * C_prime_2) * sin(gimp_deg_to_rad(delta_h_prime / 2));

  // Calculate CIEDE2000
  gdouble L_prime_average = (lab1.L + lab2.L) / 2.0;
  gdouble C_prime_average = (C_prime_1 + C_prime_2) / 2.0;

  //Calculate h_prime_average

  gdouble h_prime_average;
  if (C_prime_1 * C_prime_2 == 0) h_prime_average = 0;
  else
  {
      if (h_bar <= 180.0)
      {
          h_prime_average = (h_prime_1 + h_prime_2) / 2;
      }
      else if (h_bar > 180.0 && (h_prime_1 + h_prime_2) < 360.0)
      {
          h_prime_average = (h_prime_1 + h_prime_2 + 360.0) / 2;
      }
      else
      {
          h_prime_average = (h_prime_1 + h_prime_2 - 360.0) / 2;
      }
  }
  gdouble L_prime_average_minus_50_square = (L_prime_average - 50);
  L_prime_average_minus_50_square *= L_prime_average_minus_50_square;

  gdouble S_L = 1 + ((.015d * L_prime_average_minus_50_square) / sqrt(20 + L_prime_average_minus_50_square));
  gdouble S_C = 1 + .045d * C_prime_average;
  gdouble T = 1
      - .17 * cos(gimp_deg_to_rad(h_prime_average - 30))
      + .24 * cos(gimp_deg_to_rad(h_prime_average * 2))
      + .32 * cos(gimp_deg_to_rad(h_prime_average * 3 + 6))
      - .2 * cos(gimp_deg_to_rad(h_prime_average * 4 - 63));
  gdouble S_H = 1 + .015 * T * C_prime_average;
  gdouble h_prime_average_minus_275_div_25_square = (h_prime_average - 275) / (25);
  h_prime_average_minus_275_div_25_square *= h_prime_average_minus_275_div_25_square;
  gdouble delta_theta = 30 * exp(-h_prime_average_minus_275_div_25_square);

  gdouble C_prime_average_pot_7 = C_prime_average * C_prime_average * C_prime_average;
  C_prime_average_pot_7 *= C_prime_average_pot_7 * C_prime_average;
  gdouble R_C = 2 * sqrt(C_prime_average_pot_7 / (C_prime_average_pot_7 + 6103515625));

  gdouble R_T = -sin(gimp_deg_to_rad(2 * delta_theta)) * R_C;

  gdouble delta_L_prime_div_k_L_S_L = delta_L_prime / (S_L * k_L);
  gdouble delta_C_prime_div_k_C_S_C = delta_C_prime / (S_C * k_C);
  gdouble delta_H_prime_div_k_H_S_H = delta_H_prime / (S_H * k_H);

  gdouble CIEDE2000 = sqrt(
      delta_L_prime_div_k_L_S_L * delta_L_prime_div_k_L_S_L
      + delta_C_prime_div_k_C_S_C * delta_C_prime_div_k_C_S_C
      + delta_H_prime_div_k_H_S_H * delta_H_prime_div_k_H_S_H
      + R_T * delta_C_prime_div_k_C_S_C * delta_H_prime_div_k_H_S_H
      );


  gdouble colorDiff = CIEDE2000 / 100.0;  /* normalize range [from 0.0 to 100.0] ==> [from 0.0 to 1.0] */
  if(debugPrint)
  {
    printf("L*a*b (%.3f, %.3f, %.3f) rgb 1/2 (%03d %03d %03d) / (%03d %03d %03d) CIEDE2000:%f colorDiff:%f\n"
       , lab1.L
       , lab1.A
       , lab1.B
       , (int)(aPixelPtr[0])
       , (int)(aPixelPtr[1])
       , (int)(aPixelPtr[2])
       , (int)(bPixelPtr[0])
       , (int)(bPixelPtr[1])
       , (int)(bPixelPtr[2])
       , CIEDE2000
       , colorDiff
       );
  }

  return (colorDiff);

}  /* end gap_colordiff_LabDeltaE2000 */
Example #13
0
/* This function is shared between gimp_brush_generated_transform_size and
 * gimp_brush_generated_calc, therefore we provide a bunch of optional
 * pointers for returnvalues.
 */
static void
gimp_brush_generated_get_size (GimpBrushGenerated      *gbrush,
                               GimpBrushGeneratedShape  shape,
                               gfloat                   radius,
                               gint                     spikes,
                               gfloat                   hardness,
                               gfloat                   aspect_ratio,
                               gdouble                  angle_in_degrees,
                               gint                    *width,
                               gint                    *height,
                               gdouble                 *_s,
                               gdouble                 *_c,
                               GimpVector2             *_x_axis,
                               GimpVector2             *_y_axis)
{
  gdouble      half_width  = 0.0;
  gdouble      half_height = 0.0;
  gint         w, h;
  gdouble      c, s;
  gdouble      short_radius;
  GimpVector2  x_axis;
  GimpVector2  y_axis;

  /* Since floatongpoint is not really accurate,
   * we need to round to limit the errors.
   * Errors in some border cases resulted in
   * different height and width reported for
   * the same input value on calling procedure side.
   * This became problem at the rise of dynamics that
   * allows for any angle to turn up.
   **/

  angle_in_degrees = ROUND (angle_in_degrees * 1000.0) / 1000.0;

  s = sin (gimp_deg_to_rad (angle_in_degrees));
  c = cos (gimp_deg_to_rad (angle_in_degrees));

  short_radius = radius / aspect_ratio;

  x_axis.x =        c * radius;
  x_axis.y = -1.0 * s * radius;
  y_axis.x =        s * short_radius;
  y_axis.y =        c * short_radius;

  switch (shape)
    {
    case GIMP_BRUSH_GENERATED_CIRCLE:
      half_width  = sqrt (x_axis.x * x_axis.x + y_axis.x * y_axis.x);
      half_height = sqrt (x_axis.y * x_axis.y + y_axis.y * y_axis.y);
      break;

    case GIMP_BRUSH_GENERATED_SQUARE:
      half_width  = fabs (x_axis.x) + fabs (y_axis.x);
      half_height = fabs (x_axis.y) + fabs (y_axis.y);
      break;

    case GIMP_BRUSH_GENERATED_DIAMOND:
      half_width  = MAX (fabs (x_axis.x), fabs (y_axis.x));
      half_height = MAX (fabs (x_axis.y), fabs (y_axis.y));
      break;
    }

  if (spikes > 2)
    {
      /* could be optimized by respecting the angle */
      half_width = half_height = sqrt (radius * radius +
                                       short_radius * short_radius);
      y_axis.x = s * radius;
      y_axis.y = c * radius;
    }

  w = MAX (1, ceil (half_width  * 2));
  h = MAX (1, ceil (half_height * 2));

  if (! (w & 0x1)) w++;
  if (! (h & 0x1)) h++;

  *width  = w;
  *height = h;

  /*  These will typically be set then this function is called by
   *  gimp_brush_generated_calc, which needs the values in its algorithms.
   */
  if (_s != NULL)
    *_s = s;

  if (_c != NULL)
    *_c = c;

  if (_x_axis != NULL)
    *_x_axis = x_axis;

  if (_y_axis != NULL)
    *_y_axis = y_axis;
}