示例#1
0
static gdouble
gimp_levels_config_input_from_color (GimpHistogramChannel  channel,
                                     const GimpRGB        *color)
{
  switch (channel)
    {
    case GIMP_HISTOGRAM_VALUE:
      return MAX (MAX (color->r, color->g), color->b);

    case GIMP_HISTOGRAM_RED:
      return color->r;

    case GIMP_HISTOGRAM_GREEN:
      return color->g;

    case GIMP_HISTOGRAM_BLUE:
      return color->b;

    case GIMP_HISTOGRAM_ALPHA:
      return color->a;

    case GIMP_HISTOGRAM_RGB:
      return MIN (MIN (color->r, color->g), color->b);

    case GIMP_HISTOGRAM_LUMINANCE:
      return GIMP_RGB_LUMINANCE (color->r, color->g, color->b);
    }

  return 0.0;
}
static gboolean
gimp_operation_colorize_process (GeglOperation       *operation,
                                 void                *in_buf,
                                 void                *out_buf,
                                 glong                samples,
                                 const GeglRectangle *roi,
                                 gint                 level)
{
  GimpOperationPointFilter *point  = GIMP_OPERATION_POINT_FILTER (operation);
  GimpColorizeConfig       *config = GIMP_COLORIZE_CONFIG (point->config);
  gfloat                   *src    = in_buf;
  gfloat                   *dest   = out_buf;
  GimpHSL                   hsl;

  if (! config)
    return FALSE;

  hsl.h = config->hue;
  hsl.s = config->saturation;
  hsl.a = src[ALPHA];

  while (samples--)
    {
      GimpRGB rgb;
      gfloat  lum = GIMP_RGB_LUMINANCE (src[RED],
                                        src[GREEN],
                                        src[BLUE]);

      if (config->lightness > 0)
        {
          lum = lum * (1.0 - config->lightness);

          lum += 1.0 - (1.0 - config->lightness);
        }
      else if (config->lightness < 0)
        {
          lum = lum * (config->lightness + 1.0);
        }

      hsl.l = lum;

      gimp_hsl_to_rgb (&hsl, &rgb);

      /*  the code in base/colorize.c would multiply r,b,g with lum,
       *  but this is a bug since it should multiply with 255. We
       *  don't repeat this bug here (this is the reason why the gegl
       *  colorize is brighter than the legacy one).
       */
      dest[RED]   = rgb.r; /* * lum; */
      dest[GREEN] = rgb.g; /* * lum; */
      dest[BLUE]  = rgb.b; /* * lum */;
      dest[ALPHA] = rgb.a;

      src  += 4;
      dest += 4;
    }

  return TRUE;
}
示例#3
0
/**
 * gimp_rgb_luminance:
 * @rgb:
 *
 * Return value: the luminous intensity of the range from 0.0 to 1.0.
 *
 * Since: GIMP 2.4
 **/
gdouble
gimp_rgb_luminance (const GimpRGB *rgb)
{
  gdouble luminance;

  g_return_val_if_fail (rgb != NULL, 0.0);

  luminance = GIMP_RGB_LUMINANCE (rgb->r, rgb->g, rgb->b);

  return CLAMP (luminance, 0.0, 1.0);
}
示例#4
0
static VALUE
rb_GIMP_RGB_LUMINANCE (VALUE self,
                       VALUE r,
                       VALUE g,
                       VALUE b)
{
  gdouble result;
  result = GIMP_RGB_LUMINANCE((gdouble)NUM2DBL(r),
                              (gdouble)NUM2DBL(g),
                              (gdouble)NUM2DBL(b));

  return rb_float_new(result);
}
void
gimp_operation_layer_mode_blend_luma_lighten_only (const gfloat *in,
                                                   const gfloat *layer,
                                                   gfloat       *comp,
                                                   gint          samples)
{
  while (samples--)
    {
      if (in[ALPHA] != 0.0f && layer[ALPHA] != 0.0f)
        {
          gfloat dest_luminance;
          gfloat src_luminance;
          gint   c;

          dest_luminance = GIMP_RGB_LUMINANCE (in[0],    in[1],    in[2]);
          src_luminance  = GIMP_RGB_LUMINANCE (layer[0], layer[1], layer[2]);

          if (dest_luminance >= src_luminance)
            {
              for (c = 0; c < 3; c++)
                comp[c] = in[c];
            }
          else
            {
              for (c = 0; c < 3; c++)
                comp[c] = layer[c];
            }
        }

      comp[ALPHA] = layer[ALPHA];

      comp  += 4;
      layer += 4;
      in    += 4;
    }
}
示例#6
0
static inline guchar
pixel_luminance (const guchar *p,
                 gint          bpp)
{
  switch (bpp)
    {
    case 1:
    case 2:
      return p[0];

    case 3:
    case 4:
      return GIMP_RGB_LUMINANCE (p[0], p[1], p[2]);

    default:
      return 0; /* should not be reached */
    }
}
示例#7
0
/*
  Returns NGRADSAMPLES samples of active gradient.
  Each sample has (gimp_drawable_bpp (drawable_id)) bytes.
  "ripped" from gradmap.c.
 */
static guchar *
get_gradient_samples (gint32    drawable_id,
                      gboolean  reverse)
{
  gchar   *gradient_name;
  gint     n_f_samples;
  gdouble *f_samples, *f_samp;    /* float samples */
  guchar  *b_samples, *b_samp;    /* byte samples */
  gint     bpp, color, has_alpha, alpha;
  gint     i, j;

  gradient_name = gimp_context_get_gradient ();

  gimp_gradient_get_uniform_samples (gradient_name, NGRADSAMPLES, reverse,
                                     &n_f_samples, &f_samples);

  g_free (gradient_name);

  bpp       = gimp_drawable_bpp (drawable_id);
  color     = gimp_drawable_is_rgb (drawable_id);
  has_alpha = gimp_drawable_has_alpha (drawable_id);
  alpha     = (has_alpha ? bpp - 1 : bpp);

  b_samples = g_new (guchar, NGRADSAMPLES * bpp);

  for (i = 0; i < NGRADSAMPLES; i++)
    {
      b_samp = &b_samples[i * bpp];
      f_samp = &f_samples[i * 4];

      if (color)
        for (j = 0; j < 3; j++)
          b_samp[j] = f_samp[j] * 255;
      else
        b_samp[0] = GIMP_RGB_LUMINANCE (f_samp[0], f_samp[1], f_samp[2]) * 255;

      if (has_alpha)
        b_samp[alpha] = f_samp[3] * 255;
    }

  g_free (f_samples);

  return b_samples;
}
示例#8
0
文件: oilify.c 项目: Amerekanets/gimp
/*
 * Helper function to read a sample from a mask-size/exponent map
 */
static inline gfloat
get_map_value (const guchar *src,
               gint          bpp)
{
  gfloat value;

  if (bpp >= 3)
    value = GIMP_RGB_LUMINANCE (src[0], src[1], src[2]);
  else
    value = *src;

  if (value < 1.0)
    value = 1.0;

  /*  value should be in [0,1]  */
  value /= 255.0;

  return value;
}
示例#9
0
static gdouble
displace_map_give_value (guchar *pt,
                         gint    alpha,
                         gint    bytes)
{
  gdouble ret, val_alpha;

  if (bytes >= 3)
    ret =  GIMP_RGB_LUMINANCE (pt[0], pt[1], pt[2]);
  else
    ret = (gdouble) *pt;

  if (alpha)
    {
      val_alpha = pt[bytes - 1];
      ret = ((ret - 127.5) * val_alpha / 255.0) + 127.5;
    }

  return ret;
}
示例#10
0
static void
desaturate_region_luminosity (PixelRegion    *srcPR,
                              PixelRegion    *destPR,
                              const gboolean  has_alpha)
{
  const guchar *src  = srcPR->data;
  guchar       *dest = destPR->data;
  gint          h    = srcPR->h;

  while (h--)
    {
      const guchar *s = src;
      guchar       *d = dest;
      gint          j;

      for (j = 0; j < srcPR->w; j++)
        {
          gint luminosity = GIMP_RGB_LUMINANCE (s[RED_PIX],
                                                s[GREEN_PIX],
                                                s[BLUE_PIX]) + 0.5;

          d[RED_PIX]   = luminosity;
          d[GREEN_PIX] = luminosity;
          d[BLUE_PIX]  = luminosity;

          if (has_alpha)
            d[ALPHA_PIX] = s[ALPHA_PIX];

          d += destPR->bytes;
          s += srcPR->bytes;
        }

      src += srcPR->rowstride;
      dest += destPR->rowstride;
    }
}
static void
explorer (GimpDrawable * drawable)
{
  GimpPixelRgn  srcPR;
  GimpPixelRgn  destPR;
  gint          width;
  gint          height;
  gint          bpp;
  gint          row;
  gint          x1;
  gint          y1;
  gint          x2;
  gint          y2;
  guchar       *src_row;
  guchar       *dest_row;

  /* Get the input area. This is the bounding box of the selection in
   *  the image (or the entire image if there is no selection). Only
   *  operating on the input area is simply an optimization. It doesn't
   *  need to be done for correct operation. (It simply makes it go
   *  faster, since fewer pixels need to be operated on).
   */
  gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);

  /* Get the size of the input image. (This will/must be the same
   *  as the size of the output image.
   */
  width  = drawable->width;
  height = drawable->height;
  bpp  = drawable->bpp;

  /*  allocate row buffers  */
  src_row  = g_new (guchar, bpp * (x2 - x1));
  dest_row = g_new (guchar, bpp * (x2 - x1));

  /*  initialize the pixel regions  */
  gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
  gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height, TRUE, TRUE);

  xbild = width;
  ybild = height;
  xdiff = (xmax - xmin) / xbild;
  ydiff = (ymax - ymin) / ybild;

  /* for grayscale drawables */
  if (bpp < 3)
    {
      gint     i;
      for (i = 0; i < MAXNCOLORS; i++)
          valuemap[i] = GIMP_RGB_LUMINANCE (colormap[i].r,
                                            colormap[i].g,
                                            colormap[i].b);
    }

  for (row = y1; row < y2; row++)
    {
      gimp_pixel_rgn_get_row (&srcPR, src_row, x1, row, (x2 - x1));

      explorer_render_row (src_row,
                           dest_row,
                           row,
                           (x2 - x1),
                           bpp);

      /*  store the dest  */
      gimp_pixel_rgn_set_row (&destPR, dest_row, x1, row, (x2 - x1));

      if ((row % 10) == 0)
        gimp_progress_update ((double) row / (double) (y2 - y1));
    }

  /*  update the processed region  */
  gimp_drawable_flush (drawable);
  gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
  gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), (y2 - y1));

  g_free (src_row);
  g_free (dest_row);
}
示例#12
0
void
gimp_levels_config_adjust_by_colors (GimpLevelsConfig     *config,
                                     GimpHistogramChannel  channel,
                                     const GimpRGB        *black,
                                     const GimpRGB        *gray,
                                     const GimpRGB        *white)
{
  g_return_if_fail (GIMP_IS_LEVELS_CONFIG (config));

  g_object_freeze_notify (G_OBJECT (config));

  if (black)
    {
      config->low_input[channel] = gimp_levels_config_input_from_color (channel,
                                                                        black);
      g_object_notify (G_OBJECT (config), "low-input");
    }


  if (white)
    {
      config->high_input[channel] = gimp_levels_config_input_from_color (channel,
                                                                         white);
      g_object_notify (G_OBJECT (config), "high-input");
    }

  if (gray)
    {
      gdouble input;
      gdouble range;
      gdouble inten;
      gdouble out_light;
      gdouble lightness;

      /* Calculate lightness value */
      lightness = GIMP_RGB_LUMINANCE (gray->r, gray->g, gray->b);

      input = gimp_levels_config_input_from_color (channel, gray);

      range = config->high_input[channel] - config->low_input[channel];
      if (range <= 0)
        return;

      input -= config->low_input[channel];
      if (input < 0)
        return;

      /* Normalize input and lightness */
      inten = input / range;
      out_light = lightness/ range;

      if (out_light <= 0)
        return;

      /* Map selected color to corresponding lightness */
      config->gamma[channel] = log (inten) / log (out_light);
      g_object_notify (G_OBJECT (config), "gamma");
    }

  g_object_thaw_notify (G_OBJECT (config));
}
static gboolean
gimp_operation_desaturate_process (GeglOperation       *operation,
                                   void                *in_buf,
                                   void                *out_buf,
                                   glong                samples,
                                   const GeglRectangle *roi,
                                   gint                 level)
{
  GimpOperationPointFilter *point  = GIMP_OPERATION_POINT_FILTER (operation);
  GimpDesaturateConfig     *config = GIMP_DESATURATE_CONFIG (point->config);
  gfloat                   *src    = in_buf;
  gfloat                   *dest   = out_buf;

  if (! config)
    return FALSE;

  switch (config->mode)
    {
    case GIMP_DESATURATE_LIGHTNESS:
      while (samples--)
        {
          gfloat min, max, value;

          max = MAX (src[0], src[1]);
          max = MAX (max, src[2]);
          min = MIN (src[0], src[1]);
          min = MIN (min, src[2]);

          value = (max + min) / 2;

          dest[0] = value;
          dest[1] = value;
          dest[2] = value;
          dest[3] = src[3];

          src  += 4;
          dest += 4;
        }
      break;

    case GIMP_DESATURATE_LUMINOSITY:
      while (samples--)
        {
          gfloat value = GIMP_RGB_LUMINANCE (src[0], src[1], src[2]);

          dest[0] = value;
          dest[1] = value;
          dest[2] = value;
          dest[3] = src[3];

          src  += 4;
          dest += 4;
        }
      break;

    case GIMP_DESATURATE_AVERAGE:
      while (samples--)
        {
          gfloat value = (src[0] + src[1] + src[2]) / 3;

          dest[0] = value;
          dest[1] = value;
          dest[2] = value;
          dest[3] = src[3];

          src  += 4;
          dest += 4;
        }
      break;
    }

  return TRUE;
}
示例#14
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;
}
示例#15
0
文件: oilify.c 项目: Amerekanets/gimp
/*
 * For all x and y as requested, replace the pixel at (x,y)
 * with a weighted average of the most frequently occurring
 * values in a circle of mask_size diameter centered at (x,y).
 */
static void
oilify (GimpDrawable *drawable,
        GimpPreview  *preview)
{
  gboolean      use_inten;
  gboolean      use_msmap = FALSE;
  gboolean      use_emap = FALSE;
  GimpDrawable *mask_size_map_drawable = NULL;
  GimpDrawable *exponent_map_drawable = NULL;
  GimpPixelRgn  mask_size_map_rgn;
  GimpPixelRgn  exponent_map_rgn;
  gint          msmap_bpp = 0;
  gint          emap_bpp = 0;
  GimpPixelRgn  dest_rgn;
  GimpPixelRgn *regions[3];
  gint          n_regions;
  gint          bpp;
  gint         *sqr_lut;
  gint          x1, y1, x2, y2;
  gint          width, height;
  gint          Hist[HISTSIZE];
  gint          Hist_rgb[4][HISTSIZE];
  gpointer      pr;
  gint          progress, max_progress;
  guchar       *src_buf;
  guchar       *src_inten_buf = NULL;
  gint          i;

  use_inten = (ovals.mode == MODE_INTEN);

  /*  Get the selection bounds  */
  if (preview)
    {
      gimp_preview_get_position (preview, &x1, &y1);
      gimp_preview_get_size (preview, &width, &height);

      x2 = x1 + width;
      y2 = y1 + height;
    }
  else
    {
      gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
      width  = x2 - x1;
      height = y2 - y1;
    }

  progress = 0;
  max_progress = width * height;

  bpp = drawable->bpp;

  /*
   * Look-up-table implementation of the square function, for use in the
   * VERY TIGHT inner loops
   */
  {
    gint lut_size = (gint) ovals.mask_size / 2 + 1;

    sqr_lut = g_new (gint, lut_size);

    for (i = 0; i < lut_size; i++)
      sqr_lut[i] = SQR (i);
  }

  /*  Get the map drawables, if applicable  */

  if (ovals.use_mask_size_map && ovals.mask_size_map >= 0)
    {
      use_msmap = TRUE;

      mask_size_map_drawable = gimp_drawable_get (ovals.mask_size_map);
      gimp_pixel_rgn_init (&mask_size_map_rgn, mask_size_map_drawable,
                           x1, y1, width, height, FALSE, FALSE);

      msmap_bpp = mask_size_map_drawable->bpp;
    }

  if (ovals.use_exponent_map && ovals.exponent_map >= 0)
    {
      use_emap = TRUE;

      exponent_map_drawable = gimp_drawable_get (ovals.exponent_map);
      gimp_pixel_rgn_init (&exponent_map_rgn, exponent_map_drawable,
                           x1, y1, width, height, FALSE, FALSE);

      emap_bpp = exponent_map_drawable->bpp;
    }

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

  {
    GimpPixelRgn src_rgn;

    gimp_pixel_rgn_init (&src_rgn, drawable,
                         x1, y1, width, height, FALSE, FALSE);
    src_buf = g_new (guchar, width * height * bpp);
    gimp_pixel_rgn_get_rect (&src_rgn, src_buf, x1, y1, width, height);
  }

  /*
   * If we're working in intensity mode, then generate a separate intensity
   * map of the source image. This way, we can avoid calculating the
   * intensity of any given source pixel more than once.
   */
  if (use_inten)
    {
      guchar *src;
      guchar *dest;

      src_inten_buf = g_new (guchar, width * height);

      for (i = 0,
           src = src_buf,
           dest = src_inten_buf
           ;
           i < (width * height)
           ;
           i++,
           src += bpp,
           dest++)
        {
          *dest = (guchar) GIMP_RGB_LUMINANCE (src[0], src[1], src[2]);
        }
    }

  n_regions = 0;
  regions[n_regions++] = &dest_rgn;
  if (use_msmap)
    regions[n_regions++] = &mask_size_map_rgn;
  if (use_emap)
    regions[n_regions++] = &exponent_map_rgn;

  for (pr = gimp_pixel_rgns_register2 (n_regions, regions);
       pr != NULL;
       pr = gimp_pixel_rgns_process (pr))
    {
      gint    y;
      guchar *dest_row;
      guchar *src_msmap_row = NULL;
      guchar *src_emap_row = NULL;

      for (y = dest_rgn.y,
           dest_row = dest_rgn.data,
           src_msmap_row = mask_size_map_rgn.data,  /* valid iff use_msmap */
           src_emap_row = exponent_map_rgn.data     /* valid iff use_emap */
           ;
           y < (gint) (dest_rgn.y + dest_rgn.h)
           ;
           y++,
           dest_row += dest_rgn.rowstride,
           src_msmap_row += mask_size_map_rgn.rowstride,  /* valid iff use_msmap */
           src_emap_row += exponent_map_rgn.rowstride)    /* valid iff use_emap */
        {
          gint    x;
          guchar *dest;
          guchar *src_msmap = NULL;
          guchar *src_emap = NULL;

          for (x = dest_rgn.x,
               dest = dest_row,
               src_msmap = src_msmap_row,  /* valid iff use_msmap */
               src_emap = src_emap_row     /* valid iff use_emap */
               ;
               x < (gint) (dest_rgn.x + dest_rgn.w)
               ;
               x++,
               dest += bpp,
               src_msmap += msmap_bpp,  /* valid iff use_msmap */
               src_emap += emap_bpp)    /* valid iff use_emap */
            {
              gint    radius, radius_squared;
              gfloat  exponent;
              gint    mask_x1, mask_y1;
              gint    mask_x2, mask_y2;
              gint    mask_y;
              gint    src_offset;
              guchar *src_row;
              guchar *src_inten_row = NULL;

              if (use_msmap)
                {
                  gfloat factor = get_map_value (src_msmap, msmap_bpp);

                  radius = ROUND (factor * (0.5 * ovals.mask_size));
                }
              else
                {
                  radius = (gint) ovals.mask_size / 2;
                }

              radius_squared = SQR (radius);

              exponent = ovals.exponent;
              if (use_emap)
                exponent *= get_map_value (src_emap, emap_bpp);

              if (use_inten)
                memset (Hist, 0, sizeof (Hist));

              memset (Hist_rgb, 0, sizeof (Hist_rgb));

              mask_x1 = CLAMP ((x - radius), x1, x2);
              mask_y1 = CLAMP ((y - radius), y1, y2);
              mask_x2 = CLAMP ((x + radius + 1), x1, x2);
              mask_y2 = CLAMP ((y + radius + 1), y1, y2);

              src_offset = (mask_y1 - y1) * width + (mask_x1 - x1);

              for (mask_y = mask_y1,
                   src_row = src_buf + src_offset * bpp,
                   src_inten_row = src_inten_buf + src_offset  /* valid iff use_inten */
                   ;
                   mask_y < mask_y2
                   ;
                   mask_y++,
                   src_row += width * bpp,
                   src_inten_row += width)  /* valid iff use_inten */
                {
                  guchar *src;
                  guchar *src_inten = NULL;
                  gint    dy_squared = sqr_lut[ABS (mask_y - y)];
                  gint    mask_x;

                  for (mask_x = mask_x1,
                       src = src_row,
                       src_inten = src_inten_row  /* valid iff use_inten */
                       ;
                       mask_x < mask_x2
                       ;
                       mask_x++,
                       src += bpp,
                       src_inten++)  /* valid iff use_inten */
                    {
                      gint dx_squared = sqr_lut[ABS (mask_x - x)];
                      gint b;

                      /*  Stay inside a circular mask area  */
                      if ((dx_squared + dy_squared) > radius_squared)
                        continue;

                      if (use_inten)
                        {
                          gint inten = *src_inten;
                          ++Hist[inten];
                          for (b = 0; b < bpp; b++)
                            Hist_rgb[b][inten] += src[b];
                        }
                      else
                        {
                          for (b = 0; b < bpp; b++)
                            ++Hist_rgb[b][src[b]];
                        }

                    } /* for mask_x */
                } /* for mask_y */

              if (use_inten)
                {
                  weighted_average_color (Hist, Hist_rgb, exponent, dest, bpp);
                }
              else
                {
                  gint b;

                  for (b = 0; b < bpp; b++)
                    dest[b] = weighted_average_value (Hist_rgb[b], exponent);
                }

            } /* for x */
        } /* for y */

      if (preview)
        {
          gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview),
                                             &dest_rgn);
        }
      else
        {
          progress += dest_rgn.w * dest_rgn.h;
          gimp_progress_update ((gdouble) progress / (gdouble) max_progress);
        }
    } /* for pr */

  /*  Detach from the map drawables  */
  if (mask_size_map_drawable)
    gimp_drawable_detach (mask_size_map_drawable);

  if (exponent_map_drawable)
    gimp_drawable_detach (exponent_map_drawable);

  if (src_inten_buf)
    g_free (src_inten_buf);

  g_free (src_buf);
  g_free (sqr_lut);

  if (!preview)
    {
      /*  Update the oil-painted region  */
      gimp_drawable_flush (drawable);
      gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
      gimp_drawable_update (drawable->drawable_id, x1, y1, width, height);
    }
}
示例#16
0
/* This function chooses a gray value for the text color, based on
 * the average luminance of the text area of the splash image.
 */
static gboolean
splash_average_text_area (GimpSplash *splash,
                          GdkPixbuf  *pixbuf,
                          GdkColor   *color)
{
  const guchar *pixels;
  gint          rowstride;
  gint          channels;
  gint          luminance = 0;
  guint         sum[3]    = { 0, 0, 0 };
  GdkRectangle  image     = { 0, 0, 0, 0 };
  GdkRectangle  area      = { 0, 0, 0, 0 };

  g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE);
  g_return_val_if_fail (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8, FALSE);

  image.width  = gdk_pixbuf_get_width (pixbuf);
  image.height = gdk_pixbuf_get_height (pixbuf);
  rowstride    = gdk_pixbuf_get_rowstride (pixbuf);
  channels     = gdk_pixbuf_get_n_channels (pixbuf);
  pixels       = gdk_pixbuf_get_pixels (pixbuf);

  splash_position_layouts (splash, "Short text", "Somewhat longer text", &area);
  splash_position_layouts (splash, "", "", NULL);

  if (gdk_rectangle_intersect (&image, &area, &area))
    {
      const gint count = area.width * area.height;
      gint       x, y;

      pixels += area.x * channels;
      pixels += area.y * rowstride;

      for (y = 0; y < area.height; y++)
        {
          const guchar *src = pixels;

          for (x = 0; x < area.width; x++)
            {
              sum[0] += src[0];
              sum[1] += src[1];
              sum[2] += src[2];

              src += channels;
            }

          pixels += rowstride;
        }

      luminance = GIMP_RGB_LUMINANCE (sum[0] / count,
                                      sum[1] / count,
                                      sum[2] / count);

      luminance = CLAMP0255 (luminance > 127 ?
                             luminance - 223 : luminance + 223);

    }

  color->red = color->green = color->blue = (luminance << 8 | luminance);

  return gdk_colormap_alloc_color (gtk_widget_get_colormap (splash->area),
                                   color, FALSE, TRUE);
}
示例#17
0
void
gimp_levels_config_adjust_by_colors (GimpLevelsConfig     *config,
                                     GimpHistogramChannel  channel,
                                     const GimpRGB        *black,
                                     const GimpRGB        *gray,
                                     const GimpRGB        *white)
{
  g_return_if_fail (GIMP_IS_LEVELS_CONFIG (config));

  g_object_freeze_notify (G_OBJECT (config));

  if (black)
    {
      config->low_input[channel] = gimp_levels_config_input_from_color (channel,
                                                                        black);
      g_object_notify (G_OBJECT (config), "low-input");
    }


  if (white)
    {
      config->high_input[channel] = gimp_levels_config_input_from_color (channel,
                                                                         white);
      g_object_notify (G_OBJECT (config), "high-input");
    }

  if (gray)
    {
      gdouble input;
      gdouble range;
      gdouble inten;
      gdouble out_light;
      gdouble lightness;

      /* Calculate lightness value */
      lightness = GIMP_RGB_LUMINANCE (gray->r, gray->g, gray->b);

      input = gimp_levels_config_input_from_color (channel, gray);

      range = config->high_input[channel] - config->low_input[channel];
      if (range <= 0)
        goto out;

      input -= config->low_input[channel];
      if (input < 0)
        goto out;

      /* Normalize input and lightness */
      inten = input / range;
      out_light = lightness / range;

      /* See bug 622054: picking pure black or white as gamma doesn't
       * work. But we cannot compare to 0.0 or 1.0 because cpus and
       * compilers are shit. If you try to check out_light using
       * printf() it will give exact 0.0 or 1.0 anyway, probably
       * because the generated code is different and out_light doesn't
       * live in a register. That must be why the cpu/compiler mafia
       * invented epsilon and defined this shit to be the programmer's
       * responsibility.
       */
      if (out_light <= 0.0001 || out_light >= 0.9999)
        goto out;

      /* Map selected color to corresponding lightness */
      config->gamma[channel] = log (inten) / log (out_light);
      config->gamma[channel] = CLAMP (config->gamma[channel], 0.1, 10.0);
      g_object_notify (G_OBJECT (config), "gamma");
    }

 out:
  g_object_thaw_notify (G_OBJECT (config));
}
static gboolean
gimp_operation_desaturate_process (GeglOperation       *operation,
                                   void                *in_buf,
                                   void                *out_buf,
                                   glong                samples,
                                   const GeglRectangle *roi,
                                   gint                 level)
{
  GimpOperationDesaturate *desaturate = GIMP_OPERATION_DESATURATE (operation);
  gfloat                  *src        = in_buf;
  gfloat                  *dest       = out_buf;

  switch (desaturate->mode)
    {
    case GIMP_DESATURATE_LIGHTNESS:
      while (samples--)
        {
          gfloat min, max, value;

          max = MAX (src[0], src[1]);
          max = MAX (max, src[2]);
          min = MIN (src[0], src[1]);
          min = MIN (min, src[2]);

          value = (max + min) / 2;

          dest[0] = value;
          dest[1] = value;
          dest[2] = value;
          dest[3] = src[3];

          src  += 4;
          dest += 4;
        }
      break;

    case GIMP_DESATURATE_LUMA:
    case GIMP_DESATURATE_LUMINANCE:
      while (samples--)
        {
          gfloat value = GIMP_RGB_LUMINANCE (src[0], src[1], src[2]);

          dest[0] = value;
          dest[1] = value;
          dest[2] = value;
          dest[3] = src[3];

          src  += 4;
          dest += 4;
        }
      break;

    case GIMP_DESATURATE_AVERAGE:
      while (samples--)
        {
          gfloat value = (src[0] + src[1] + src[2]) / 3;

          dest[0] = value;
          dest[1] = value;
          dest[2] = value;
          dest[3] = src[3];

          src  += 4;
          dest += 4;
        }
      break;
    }

  return TRUE;
}