Exemple #1
0
static void
extract_hsl (const guchar  *src,
	     gint           bpp,
	     gint           numpix,
	     guchar       **dst)
{
  register const guchar *rgb_src = src;
  register guchar *hue_dst = dst[0];
  register guchar *sat_dst = dst[1];
  register guchar *lum_dst = dst[2];
  register gint count = numpix, offset = bpp;

  while (count-- > 0)
    {
      GimpRGB rgb;
      GimpHSL hsl;

      gimp_rgb_set_uchar (&rgb, rgb_src[0], rgb_src[1], rgb_src[2]);
      gimp_rgb_to_hsl (&rgb, &hsl);

      *hue_dst++ = (guchar) (hsl.h * 255.999);
      *sat_dst++ = (guchar) (hsl.s * 255.999);
      *lum_dst++ = (guchar) (hsl.l * 255.999);

      rgb_src += offset;
    }
}
static guchar*
rgb_to_hsl (GimpDrawable     *drawable,
            LICEffectChannel  effect_channel)
{
  guchar       *themap, data[4];
  gint          x, y;
  GimpRGB       color;
  GimpHSL       color_hsl;
  gdouble       val = 0.0;
  glong         maxc, index = 0;
  GimpPixelRgn  region;
  GRand        *gr;

  gr = g_rand_new ();

  maxc = drawable->width * drawable->height;

  gimp_pixel_rgn_init (&region, drawable, border_x, border_y,
                       border_w, border_h, FALSE, FALSE);

  themap = g_new (guchar, maxc);

  for (y = 0; y < region.h; y++)
    {
      for (x = 0; x < region.w; x++)
        {
          data[3] = 255;

          gimp_pixel_rgn_get_pixel (&region, data, x, y);
          gimp_rgba_set_uchar (&color, data[0], data[1], data[2], data[3]);
          gimp_rgb_to_hsl (&color, &color_hsl);

          switch (effect_channel)
            {
            case LIC_HUE:
              val = color_hsl.h * 255;
              break;
            case LIC_SATURATION:
              val = color_hsl.s * 255;
              break;
            case LIC_BRIGHTNESS:
              val = color_hsl.l * 255;
              break;
            }

          /* add some random to avoid unstructured areas. */
          val += g_rand_double_range (gr, -1.0, 1.0);

          themap[index++] = (guchar) CLAMP0255 (RINT (val));
        }
    }

  g_rand_free (gr);

  return themap;
}
static void
gimp_colorize_config_set_property (GObject      *object,
                                   guint         property_id,
                                   const GValue *value,
                                   GParamSpec   *pspec)
{
  GimpColorizeConfig *self = GIMP_COLORIZE_CONFIG (object);

  switch (property_id)
    {
    case PROP_HUE:
      self->hue = g_value_get_double (value);
      g_object_notify (object, "color");
      break;

    case PROP_SATURATION:
      self->saturation = g_value_get_double (value);
      g_object_notify (object, "color");
      break;

    case PROP_LIGHTNESS:
      self->lightness = g_value_get_double (value);
      g_object_notify (object, "color");
      break;

    case PROP_COLOR:
      {
        GimpRGB rgb;
        GimpHSL hsl;

        gimp_value_get_rgb (value, &rgb);
        gimp_rgb_to_hsl (&rgb, &hsl);

        if (hsl.h == -1)
          hsl.h = self->hue;

        if (hsl.l == 0.0 || hsl.l == 1.0)
          hsl.s = self->saturation;

        g_object_set (self,
                      "hue",        hsl.h,
                      "saturation", hsl.s,
                      "lightness",  hsl.l * 2.0 - 1.0,
                      NULL);
      }
      break;

   default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}
Exemple #4
0
static void
transform (guchar *r,
           guchar *g,
           guchar *b)
{
  switch (wvals.colormodel)
    {
    case HSL_MODEL:
      {
        GimpHSL hsl;
        GimpRGB rgb;

        gimp_rgb_set_uchar (&rgb, *r, *g, *b);
        gimp_rgb_to_hsl (&rgb, &hsl);

        if (wvals.redmode)
          hsl.h = 0.5 * (1.0 + sin (((2 * hsl.h - 1.0) * wvals.redfrequency +
                                     wvals.redangle / 180.0) * G_PI));

        if (wvals.greenmode)
          hsl.s = 0.5 * (1.0 + sin (((2 * hsl.s - 1.0) * wvals.greenfrequency +
                                     wvals.greenangle / 180.0) * G_PI));

        if (wvals.bluemode)
          hsl.l = 0.5 * (1.0 + sin (((2 * hsl.l - 1.0) * wvals.bluefrequency +
                                     wvals.blueangle / 180.0) * G_PI));

        gimp_hsl_to_rgb (&hsl, &rgb);
        gimp_rgb_get_uchar (&rgb, r, g, b);
      }
      break;

    case RGB_MODEL:
      if (wvals.redmode)
        *r = ROUND (127.5 * (1.0 +
                             sin (((*r / 127.5 - 1.0) * wvals.redfrequency +
                                   wvals.redangle / 180.0) * G_PI)));

      if (wvals.greenmode)
        *g = ROUND (127.5 * (1.0 +
                             sin (((*g / 127.5 - 1.0) * wvals.greenfrequency +
                                   wvals.greenangle / 180.0) * G_PI)));

      if (wvals.bluemode)
        *b = ROUND (127.5 * (1.0 +
                             sin (((*b / 127.5 - 1.0) * wvals.bluefrequency +
                                   wvals.blueangle / 180.0) * G_PI)));
      break;
    }
}
Exemple #5
0
static int l_get_hsl (lua_State * lua)
{
  Priv *p;
  lua_Number x, y;
  lua_Number img_no = 0;

  lua_Number pixel[4];

  lua_pushstring (lua, "priv");
  lua_gettable (lua, LUA_REGISTRYINDEX);
  p = lua_touserdata (lua, -1);
  lua_pop(lua, 1);

  switch (lua_gettop (lua))
    {
    case 3:
      img_no = lua_tonumber(lua, -3);
      break;
    case 2:
      img_no = 0;
      break;
    default:
      lua_pushstring (lua, "incorrect number of arguments to get_rgb ([image_no,] x, y)\n");
      lua_error (lua);
      break;
  }
  x = lua_tonumber(lua, -2);
  y = lua_tonumber(lua, -1);

    get_rgba_pixel (p, img_no, x, y, pixel);

#if 0
    {
      GimpRGB rgb;
      GimpHSL hsl;

      rgb.r = pixel[0];
      rgb.g = pixel[1];
      rgb.b = pixel[2];

      gimp_rgb_to_hsl (&rgb, &hsl);

      lua_pushnumber (lua, hsl.h );
      lua_pushnumber (lua, hsl.s );
      lua_pushnumber (lua, hsl.l );
    }
#endif

  return 3;
}
void
gimp_operation_hue_saturation_map (GimpHueSaturationConfig *config,
                                   const GimpRGB           *color,
                                   GimpHueRange             range,
                                   GimpRGB                 *result)
{
  GimpHSL hsl;

  g_return_if_fail (GIMP_IS_HUE_SATURATION_CONFIG (config));
  g_return_if_fail (color != NULL);
  g_return_if_fail (result != NULL);

  gimp_rgb_to_hsl (color, &hsl);

  hsl.h = map_hue        (config, range, hsl.h);
  hsl.s = map_saturation (config, range, hsl.s);
  hsl.l = map_lightness  (config, range, hsl.l);

  gimp_hsl_to_rgb (&hsl, result);
}
static gboolean
gimp_operation_hue_saturation_process (GeglOperation       *operation,
                                       void                *in_buf,
                                       void                *out_buf,
                                       glong                samples,
                                       const GeglRectangle *roi)
{
  GimpOperationPointFilter *point  = GIMP_OPERATION_POINT_FILTER (operation);
  GimpHueSaturationConfig  *config = GIMP_HUE_SATURATION_CONFIG (point->config);
  gfloat                   *src    = in_buf;
  gfloat                   *dest   = out_buf;
  gfloat                    overlap;

  if (! config)
    return FALSE;

  overlap = config->overlap / 2.0;

  while (samples--)
    {
      GimpRGB  rgb;
      GimpHSL  hsl;
      gdouble  h;
      gint     hue_counter;
      gint     hue                 = 0;
      gint     secondary_hue       = 0;
      gboolean use_secondary_hue   = FALSE;
      gfloat   primary_intensity   = 0.0;
      gfloat   secondary_intensity = 0.0;

      rgb.r = src[RED];
      rgb.g = src[GREEN];
      rgb.b = src[BLUE];

      gimp_rgb_to_hsl (&rgb, &hsl);

      h = hsl.h * 6.0;

      for (hue_counter = 0; hue_counter < 7; hue_counter++)
        {
          gdouble hue_threshold = (gdouble) hue_counter + 0.5;

          if (h < ((gdouble) hue_threshold + overlap))
            {
              hue = hue_counter;

              if (overlap > 0.0 && h > ((gdouble) hue_threshold - overlap))
                {
                  use_secondary_hue = TRUE;

                  secondary_hue = hue_counter + 1;

                  secondary_intensity =
                    (h - (gdouble) hue_threshold + overlap) / (2.0 * overlap);

                  primary_intensity = 1.0 - secondary_intensity;
                }
              else
                {
                  use_secondary_hue = FALSE;
                }

              break;
            }
        }

      if (hue >= 6)
        {
          hue = 0;
          use_secondary_hue = FALSE;
        }

      if (secondary_hue >= 6)
        {
          secondary_hue = 0;
        }

      /*  transform into GimpHueRange values  */
      hue++;
      secondary_hue++;

      if (use_secondary_hue)
        {
          gdouble mapped_primary_hue;
          gdouble mapped_secondary_hue;
          gdouble diff;

          mapped_primary_hue   = map_hue (config, hue,           hsl.h);
          mapped_secondary_hue = map_hue (config, secondary_hue, hsl.h);

          /* Find nearest hue on the circle between primary and
           * secondary hue
           */
          diff = mapped_primary_hue - mapped_secondary_hue;
          if (diff < -0.5)
            {
              mapped_secondary_hue -= 1.0;
            }
          else if (diff >= 0.5)
            {
              mapped_secondary_hue += 1.0;
            }

          hsl.h = (mapped_primary_hue   * primary_intensity +
                   mapped_secondary_hue * secondary_intensity);

          hsl.s = (map_saturation (config, hue,           hsl.s) * primary_intensity +
                   map_saturation (config, secondary_hue, hsl.s) * secondary_intensity);

          hsl.l = (map_lightness (config, hue,           hsl.l) * primary_intensity +
                   map_lightness (config, secondary_hue, hsl.l) * secondary_intensity);
        }
      else
        {
          hsl.h = map_hue        (config, hue, hsl.h);
          hsl.s = map_saturation (config, hue, hsl.s);
          hsl.l = map_lightness  (config, hue, hsl.l);
        }

      gimp_hsl_to_rgb (&hsl, &rgb);

      dest[RED]   = rgb.r;
      dest[GREEN] = rgb.g;
      dest[BLUE]  = rgb.b;
      dest[ALPHA] = src[ALPHA];

      src  += 4;
      dest += 4;
    }

  return TRUE;
}
static int
gimp_mypaint_surface_draw_dab (MyPaintSurface *base_surface,
                               float           x,
                               float           y,
                               float           radius,
                               float           color_r,
                               float           color_g,
                               float           color_b,
                               float           opaque,
                               float           hardness,
                               float           color_a,
                               float           aspect_ratio,
                               float           angle,
                               float           lock_alpha,
                               float           colorize)
{
  GimpMybrushSurface *surface = (GimpMybrushSurface *)base_surface;
  GeglBufferIterator *iter;
  GeglRectangle       dabRect;
  GimpComponentMask   component_mask = surface->component_mask;

  const float one_over_radius2 = 1.0f / (radius * radius);
  const double angle_rad = angle / 360 * 2 * M_PI;
  const float cs = cos(angle_rad);
  const float sn = sin(angle_rad);
  float normal_mode;
  float segment1_slope;
  float segment2_slope;
  float r_aa_start;

  hardness = CLAMP (hardness, 0.0f, 1.0f);
  segment1_slope = -(1.0f / hardness - 1.0f);
  segment2_slope = -hardness / (1.0f - hardness);
  aspect_ratio = MAX (1.0f, aspect_ratio);

  r_aa_start = radius - 1.0f;
  r_aa_start = MAX (r_aa_start, 0);
  r_aa_start = (r_aa_start * r_aa_start) / aspect_ratio;

  normal_mode = opaque * (1.0f - colorize);
  colorize = opaque * colorize;

  /* FIXME: This should use the real matrix values to trim aspect_ratio dabs */
  dabRect = calculate_dab_roi (x, y, radius);
  gegl_rectangle_intersect (&dabRect, &dabRect, gegl_buffer_get_extent (surface->buffer));

  if (dabRect.width <= 0 || dabRect.height <= 0)
    return 0;

  gegl_rectangle_bounding_box (&surface->dirty, &surface->dirty, &dabRect);

  iter = gegl_buffer_iterator_new (surface->buffer, &dabRect, 0,
                                   babl_format ("R'G'B'A float"),
                                   GEGL_BUFFER_READWRITE,
                                   GEGL_ABYSS_NONE);
  if (surface->paint_mask)
    {
      GeglRectangle mask_roi = dabRect;
      mask_roi.x -= surface->paint_mask_x;
      mask_roi.y -= surface->paint_mask_y;
      gegl_buffer_iterator_add (iter, surface->paint_mask, &mask_roi, 0,
                                babl_format ("Y float"),
                                GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
    }

  while (gegl_buffer_iterator_next (iter))
    {
      float *pixel = (float *)iter->data[0];
      float *mask;
      int iy, ix;

      if (surface->paint_mask)
        mask = iter->data[1];
      else
        mask = NULL;

      for (iy = iter->roi[0].y; iy < iter->roi[0].y + iter->roi[0].height; iy++)
        {
          for (ix = iter->roi[0].x; ix < iter->roi[0].x +  iter->roi[0].width; ix++)
            {
              float rr, base_alpha, alpha, dst_alpha, r, g, b, a;
              if (radius < 3.0f)
                rr = calculate_rr_antialiased (ix, iy, x, y, aspect_ratio, sn, cs, one_over_radius2, r_aa_start);
              else
                rr = calculate_rr (ix, iy, x, y, aspect_ratio, sn, cs, one_over_radius2);
              base_alpha = calculate_alpha_for_rr (rr, hardness, segment1_slope, segment2_slope);
              alpha = base_alpha * normal_mode;
              if (mask)
                alpha *= *mask;
              dst_alpha = pixel[ALPHA];
              /* a = alpha * color_a + dst_alpha * (1.0f - alpha);
               * which converts to: */
              a = alpha * (color_a - dst_alpha) + dst_alpha;
              r = pixel[RED];
              g = pixel[GREEN];
              b = pixel[BLUE];

              if (a > 0.0f)
                {
                  /* By definition the ratio between each color[] and pixel[] component in a non-pre-multipled blend always sums to 1.0f.
                   * Originaly this would have been "(color[n] * alpha * color_a + pixel[n] * dst_alpha * (1.0f - alpha)) / a",
                   * instead we only calculate the cheaper term. */
                  float src_term = (alpha * color_a) / a;
                  float dst_term = 1.0f - src_term;
                  r = color_r * src_term + r * dst_term;
                  g = color_g * src_term + g * dst_term;
                  b = color_b * src_term + b * dst_term;
                }

              if (colorize > 0.0f && base_alpha > 0.0f)
                {
                  alpha = base_alpha * colorize;
                  a = alpha + dst_alpha - alpha * dst_alpha;
                  if (a > 0.0f)
                    {
                      GimpHSL pixel_hsl, out_hsl;
                      GimpRGB pixel_rgb = {color_r, color_g, color_b};
                      GimpRGB out_rgb   = {r, g, b};
                      float src_term = alpha / a;
                      float dst_term = 1.0f - src_term;

                      gimp_rgb_to_hsl (&pixel_rgb, &pixel_hsl);
                      gimp_rgb_to_hsl (&out_rgb, &out_hsl);

                      out_hsl.h = pixel_hsl.h;
                      out_hsl.s = pixel_hsl.s;
                      gimp_hsl_to_rgb (&out_hsl, &out_rgb);

                      r = (float)out_rgb.r * src_term + r * dst_term;
                      g = (float)out_rgb.g * src_term + g * dst_term;
                      b = (float)out_rgb.b * src_term + b * dst_term;
                    }
                }

              if (component_mask != GIMP_COMPONENT_MASK_ALL)
                {
                  if (component_mask & GIMP_COMPONENT_MASK_RED)
                    pixel[RED]   = r;
                  if (component_mask & GIMP_COMPONENT_MASK_GREEN)
                    pixel[GREEN] = g;
                  if (component_mask & GIMP_COMPONENT_MASK_BLUE)
                    pixel[BLUE]  = b;
                  if (component_mask & GIMP_COMPONENT_MASK_ALPHA)
                    pixel[ALPHA] = a;
                }
              else
                {
                  pixel[RED]   = r;
                  pixel[GREEN] = g;
                  pixel[BLUE]  = b;
                  pixel[ALPHA] = a;
                }

              pixel += 4;
              if (mask)
                mask += 1;
            }
        }
    }

  return 1;
}
static gboolean
gimp_operation_color_balance_process (GeglOperation       *operation,
                                      void                *in_buf,
                                      void                *out_buf,
                                      glong                samples,
                                      const GeglRectangle *roi,
                                      gint                 level)
{
  GimpOperationPointFilter *point  = GIMP_OPERATION_POINT_FILTER (operation);
  GimpColorBalanceConfig   *config = GIMP_COLOR_BALANCE_CONFIG (point->config);
  gfloat                   *src    = in_buf;
  gfloat                   *dest   = out_buf;

  if (! config)
    return FALSE;

  while (samples--)
    {
      gfloat r = src[RED];
      gfloat g = src[GREEN];
      gfloat b = src[BLUE];
      gfloat r_n;
      gfloat g_n;
      gfloat b_n;

      GimpRGB rgb = { r, g, b};
      GimpHSL hsl;

      gimp_rgb_to_hsl (&rgb, &hsl);

      r_n = gimp_operation_color_balance_map (r, hsl.l,
                                              config->cyan_red[GIMP_SHADOWS],
                                              config->cyan_red[GIMP_MIDTONES],
                                              config->cyan_red[GIMP_HIGHLIGHTS]);

      g_n = gimp_operation_color_balance_map (g, hsl.l,
                                              config->magenta_green[GIMP_SHADOWS],
                                              config->magenta_green[GIMP_MIDTONES],
                                              config->magenta_green[GIMP_HIGHLIGHTS]);

      b_n = gimp_operation_color_balance_map (b, hsl.l,
                                              config->yellow_blue[GIMP_SHADOWS],
                                              config->yellow_blue[GIMP_MIDTONES],
                                              config->yellow_blue[GIMP_HIGHLIGHTS]);

      if (config->preserve_luminosity)
        {
          GimpHSL hsl2;

          rgb.r = r_n;
          rgb.g = g_n;
          rgb.b = b_n;
          gimp_rgb_to_hsl (&rgb, &hsl);

          rgb.r = r;
          rgb.g = g;
          rgb.b = b;
          gimp_rgb_to_hsl (&rgb, &hsl2);

          hsl.l = hsl2.l;

          gimp_hsl_to_rgb (&hsl, &rgb);

          r_n = rgb.r;
          g_n = rgb.g;
          b_n = rgb.b;
        }

      dest[RED]   = r_n;
      dest[GREEN] = g_n;
      dest[BLUE]  = b_n;
      dest[ALPHA] = src[ALPHA];

      src  += 4;
      dest += 4;
    }

  return TRUE;
}
static gboolean
gimp_operation_color_mode_process (GeglOperation       *operation,
                                   void                *in_buf,
                                   void                *aux_buf,
                                   void                *aux2_buf,
                                   void                *out_buf,
                                   glong                samples,
                                   const GeglRectangle *roi,
                                   gint                 level)
{
  gdouble        opacity  = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
  gfloat        *in       = in_buf;
  gfloat        *layer    = aux_buf;
  gfloat        *mask     = aux2_buf;
  gfloat        *out      = out_buf;
  const gboolean has_mask = mask != NULL;

  while (samples--)
    {
      GimpHSL layer_hsl, out_hsl;
      GimpRGB layer_rgb = {layer[0], layer[1], layer[2]};
      GimpRGB out_rgb   = {in[0], in[1], in[2]};
      gfloat  comp_alpha, new_alpha;

      comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity;
      if (has_mask)
        comp_alpha *= *mask;

      new_alpha = in[ALPHA] + (1.0 - in[ALPHA]) * comp_alpha;

      if (comp_alpha && new_alpha)
        {
          gint   b;
          gfloat ratio = comp_alpha / new_alpha;

          gimp_rgb_to_hsl (&layer_rgb, &layer_hsl);
          gimp_rgb_to_hsl (&out_rgb, &out_hsl);

          out_hsl.h = layer_hsl.h;
          out_hsl.s = layer_hsl.s;
          gimp_hsl_to_rgb (&out_hsl, &out_rgb);

          out[0] = out_rgb.r;
          out[1] = out_rgb.g;
          out[2] = out_rgb.b;

          for (b = RED; b < ALPHA; b++)
            {
              out[b] = out[b] * ratio + in[b] * (1.0 - ratio);
            }
        }
      else
        {
          gint b;

          for (b = RED; b < ALPHA; b++)
            {
              out[b] = in[b];
            }
        }

      out[ALPHA] = in[ALPHA];

      in    += 4;
      layer += 4;
      out   += 4;

      if (has_mask)
        mask++;
    }

  return TRUE;
}