static gboolean
gimp_operation_saturation_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--)
    {
      GimpHSV layer_hsv, out_hsv;
      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_hsv (&layer_rgb, &layer_hsv);
          gimp_rgb_to_hsv (&out_rgb, &out_hsv);

          out_hsv.s = layer_hsv.s;
          gimp_hsv_to_rgb (&out_hsv, &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;
}
gboolean
gimp_operation_saturation_mode_process_pixels (gfloat              *in,
                                               gfloat              *layer,
                                               gfloat              *mask,
                                               gfloat              *out,
                                               gfloat               opacity,
                                               glong                samples,
                                               const GeglRectangle *roi,
                                               gint                 level)
{
  const gboolean has_mask = mask != NULL;

  while (samples--)
    {
      GimpHSV layer_hsv, out_hsv;
      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_hsv (&layer_rgb, &layer_hsv);
          gimp_rgb_to_hsv (&out_rgb, &out_hsv);

          out_hsv.s = layer_hsv.s;
          gimp_hsv_to_rgb (&out_hsv, &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;
}
/**
 * gimp_scanner_parse_color:
 * @scanner:
 * @dest:
 *
 * Return value:
 *
 * Since: GIMP 2.4
 **/
gboolean
gimp_scanner_parse_color (GScanner *scanner,
                          GimpRGB  *dest)
{
  guint      scope_id;
  guint      old_scope_id;
  GTokenType token;
  GimpRGB    color = { 0.0, 0.0, 0.0, 1.0 };

  scope_id = g_quark_from_static_string ("gimp_scanner_parse_color");
  old_scope_id = g_scanner_set_scope (scanner, scope_id);

  if (! g_scanner_scope_lookup_symbol (scanner, scope_id, "color-rgb"))
    {
      g_scanner_scope_add_symbol (scanner, scope_id,
                                  "color-rgb", GINT_TO_POINTER (COLOR_RGB));
      g_scanner_scope_add_symbol (scanner, scope_id,
                                  "color-rgba", GINT_TO_POINTER (COLOR_RGBA));
      g_scanner_scope_add_symbol (scanner, scope_id,
                                  "color-hsv", GINT_TO_POINTER (COLOR_HSV));
      g_scanner_scope_add_symbol (scanner, scope_id,
                                  "color-hsva", GINT_TO_POINTER (COLOR_HSVA));
    }

  token = G_TOKEN_LEFT_PAREN;

  while (g_scanner_peek_next_token (scanner) == token)
    {
      token = g_scanner_get_next_token (scanner);

      switch (token)
        {
        case G_TOKEN_LEFT_PAREN:
          token = G_TOKEN_SYMBOL;
          break;

        case G_TOKEN_SYMBOL:
          {
            gdouble  col[4]     = { 0.0, 0.0, 0.0, 1.0 };
            gint     n_channels = 4;
            gboolean is_hsv     = FALSE;
            gint     i;

            switch (GPOINTER_TO_INT (scanner->value.v_symbol))
              {
              case COLOR_RGB:
                n_channels = 3;
                /* fallthrough */
              case COLOR_RGBA:
                break;

              case COLOR_HSV:
                n_channels = 3;
                /* fallthrough */
              case COLOR_HSVA:
                is_hsv = TRUE;
                break;
              }

            token = G_TOKEN_FLOAT;

            for (i = 0; i < n_channels; i++)
              {
                if (! gimp_scanner_parse_float (scanner, &col[i]))
                  goto finish;
              }

            if (is_hsv)
              {
                GimpHSV hsv;

                gimp_hsva_set (&hsv, col[0], col[1], col[2], col[3]);
                gimp_hsv_clamp (&hsv);

                gimp_hsv_to_rgb (&hsv, &color);
              }
            else
              {
                gimp_rgba_set (&color, col[0], col[1], col[2], col[3]);
                gimp_rgb_clamp (&color);
              }

            token = G_TOKEN_RIGHT_PAREN;
          }
          break;

        case G_TOKEN_RIGHT_PAREN:
          token = G_TOKEN_NONE; /* indicates success */
          goto finish;

        default: /* do nothing */
          break;
        }
    }

 finish:

  if (token != G_TOKEN_NONE)
    {
      g_scanner_get_next_token (scanner);
      g_scanner_unexp_token (scanner, token, NULL, NULL, NULL,
                             _("fatal parse error"), TRUE);
    }
  else
    {
      *dest = color;
    }

  g_scanner_set_scope (scanner, old_scope_id);

  return (token == G_TOKEN_NONE);
}
Beispiel #4
0
static void
nova (GimpDrawable *drawable,
      GimpPreview  *preview)
{
   GimpPixelRgn  src_rgn;
   GimpPixelRgn  dest_rgn;
   gpointer      pr;
   guchar       *src_row, *dest_row, *save_src;
   guchar       *src, *dest;
   gint          x1, y1, x2, y2, x, y;
   gint          row, col;
   gint          alpha, bpp;
   gint          progress, max_progress;
   gboolean      has_alpha;
   gint          xc, yc; /* center of nova */
   gdouble       u, v, l, w, w1, c, t;
   gdouble      *spoke;
   gdouble       nova_alpha, src_alpha, new_alpha = 0.0;
   gdouble       compl_ratio, ratio;
   GimpRGB       color;
   GimpRGB      *spokecolor;
   GimpHSV       hsv;
   gdouble       spokecol;
   gint          i;
   GRand        *gr;
   guchar       *cache = NULL;
   gint          width, height;
   gdouble       zoom = 0.0;

   gr = g_rand_new ();

   /* initialize */
   has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);

   spoke = g_new (gdouble, pvals.nspoke);
   spokecolor = g_new (GimpRGB, pvals.nspoke);

   gimp_rgb_set_alpha (&pvals.color, 1.0);
   gimp_rgb_to_hsv (&pvals.color, &hsv);

   for (i = 0; i < pvals.nspoke; i++)
     {
       spoke[i] = gauss (gr);

       hsv.h += ((gdouble) pvals.randomhue / 360.0) *
                g_rand_double_range (gr, -0.5, 0.5);

       if (hsv.h < 0)
         hsv.h += 1.0;
       else if (hsv.h >= 1.0)
         hsv.h -= 1.0;

       gimp_hsv_to_rgb (&hsv, spokecolor + i);
     }

   if (preview)
     {
       cache = gimp_zoom_preview_get_source (GIMP_ZOOM_PREVIEW (preview),
                                             &width, &height, &bpp);

       zoom = gimp_zoom_preview_get_factor (GIMP_ZOOM_PREVIEW (preview));

       gimp_preview_transform (preview,
                               pvals.xcenter, pvals.ycenter, &xc, &yc);

       x1 = 0;
       y1 = 0;
       x2 = width;
       y2 = height;
     }
   else
     {
       gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
       bpp = gimp_drawable_bpp (drawable->drawable_id);
       xc = pvals.xcenter;
       yc = pvals.ycenter;

       gimp_pixel_rgn_init (&src_rgn, drawable,
                            x1, y1, x2-x1, y2-y1, FALSE, FALSE);
       gimp_pixel_rgn_init (&dest_rgn, drawable,
                            x1, y1, x2-x1, y2-y1, TRUE, TRUE);
     }

   alpha = (has_alpha) ? bpp - 1 : bpp;

   /* Initialize progress */
   progress     = 0;
   max_progress = (x2 - x1) * (y2 - y1);

   if (preview)
     {
       save_src = src_row  = g_new (guchar, y2 * width * bpp);
       memcpy (src_row, cache, y2 * width * bpp);

       dest_row = g_new (guchar, y2 * width * bpp);
       dest = dest_row;
       src  = src_row;

       for (row = 0, y = 0; row < y2; row++, y++)
         {

           for (col = 0, x = 0; col < x2; col++, x++)
             {
               u = ((gdouble) (x - xc) /
                    ((gdouble) pvals.radius * width /
                     drawable->width * zoom));
               v = ((gdouble) (y - yc) /
                    ((gdouble) pvals.radius * height /
                     drawable->height * zoom));

               l = sqrt (SQR (u) + SQR (v));

               /* This algorithm is still under construction. */
               t = (atan2 (u, v) / (2 * G_PI) + .51) * pvals.nspoke;
               i = (gint) floor (t);
               t -= i;
               i %= pvals.nspoke;
               w1 = spoke[i] * (1 - t) + spoke[(i + 1) % pvals.nspoke] * t;
               w1 = w1 * w1;

               w = 1.0 / (l + 0.001) * 0.9;

               nova_alpha = CLAMP (w, 0.0, 1.0);

               if (has_alpha)
               {
                 src_alpha = (gdouble) src[alpha] / 255.0;
                 new_alpha = src_alpha + (1.0 - src_alpha) * nova_alpha;
                 if (new_alpha != 0.0)
                   ratio = nova_alpha / new_alpha;
                 else
                   ratio = 0.0;
               }
               else
                 ratio = nova_alpha;

               compl_ratio = 1.0 - ratio;

               /* red or gray */
               spokecol = (gdouble)spokecolor[i                   ].r * (1.0-t) +
                          (gdouble)spokecolor[(i+1) % pvals.nspoke].r * t;

               if (w>1.0)
                 color.r = CLAMP (spokecol * w, 0.0, 1.0);
               else
                 color.r = src[0]/255.0 * compl_ratio + spokecol * ratio;
               c = CLAMP (w1 * w, 0.0, 1.0);
               color.r += c;
               dest[0] = CLAMP (color.r*255.0, 0, 255);

               if (bpp>2)
               {
                 /* green */
                 spokecol = (gdouble)spokecolor[i                   ].g * (1.0-t) +
                            (gdouble)spokecolor[(i+1) % pvals.nspoke].g * t;

                 if (w>1.0)
                   color.g = CLAMP (spokecol * w, 0.0, 1.0);
                 else
                   color.g = src[1]/255.0 * compl_ratio + spokecol * ratio;
                 c = CLAMP (w1 * w, 0.0, 1.0);
                 color.g += c;
                 dest[1] = CLAMP (color.g*255.0, 0, 255);

                 /* blue */
                 spokecol = (gdouble)spokecolor[i                   ].b * (1.0-t) +
                            (gdouble)spokecolor[(i+1) % pvals.nspoke].b * t;

                 if (w>1.0)
                   color.b = CLAMP (spokecol * w, 0.0, 1.0);
                 else
                   color.b = src[2]/255.0 * compl_ratio + spokecol * ratio;
                 c = CLAMP (w1 * w, 0.0, 1.0);
                 color.b += c;
                 dest[2] = CLAMP (color.b*255.0, 0, 255);
               }

               /* alpha */
               if (has_alpha)
                 dest[alpha] = new_alpha * 255.0;

               src  += bpp;
               dest += bpp;
             }
         }

       gimp_preview_draw_buffer (preview, dest_row, bpp * width);

       g_free (cache);
       g_free (save_src);
       g_free (dest_row);
     }
   else
     { /* normal mode */
       for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn);
            pr != NULL ;
            pr = gimp_pixel_rgns_process (pr))
         {
           src_row = src_rgn.data;
           dest_row = dest_rgn.data;

           for (row = 0, y = src_rgn.y; row < src_rgn.h; row++, y++)
             {
               src = src_row;
               dest = dest_row;

               for (col = 0, x = src_rgn.x; col < src_rgn.w; col++, x++)
                 {
                   u = (gdouble) (x-xc) / pvals.radius;
                   v = (gdouble) (y-yc) / pvals.radius;
                   l = sqrt(u*u + v*v);

                   /* This algorithm is still under construction. */
                   t = (atan2 (u, v) / (2 * G_PI) + .51) * pvals.nspoke;
                   i = (gint) floor (t);
                   t -= i;
                   i %= pvals.nspoke;
                   w1 = spoke[i] * (1 - t) + spoke[(i + 1) % pvals.nspoke] * t;
                   w1 = w1 * w1;

                   w = 1/(l+0.001)*0.9;

                   nova_alpha = CLAMP (w, 0.0, 1.0);

                   if (has_alpha)
                     {
                       src_alpha = (gdouble) src[alpha] / 255.0;
                       new_alpha = src_alpha + (1.0 - src_alpha) * nova_alpha;

                       if (new_alpha != 0.0)
                         ratio = nova_alpha / new_alpha;
                       else
                         ratio = 0.0;
                     }
                   else
                     ratio = nova_alpha;

                   compl_ratio = 1.0 - ratio;

                   switch (bpp)
                     {
                     case 1:
                     case 2:
                       /* gray */
                       spokecol = (gdouble)spokecolor[i                   ].r * (1.0-t) +
                                  (gdouble)spokecolor[(i+1) % pvals.nspoke].r * t;
                       if (w>1.0)
                         color.r = CLAMP (spokecol * w, 0.0, 1.0);
                       else
                         color.r = src[0]/255.0 * compl_ratio + spokecol * ratio;
                       c = CLAMP (w1 * w, 0.0, 1.0);
                       color.r += c;
                       dest[0] = CLAMP (color.r*255.0, 0, 255);
                       break;

                     case 3:
                     case 4:
                       /* red */
                       spokecol = (gdouble)spokecolor[i                   ].r * (1.0-t) +
                                  (gdouble)spokecolor[(i+1) % pvals.nspoke].r * t;
                       if (w>1.0)
                         color.r = CLAMP (spokecol * w, 0.0, 1.0);
                       else
                         color.r = src[0]/255.0 * compl_ratio + spokecol * ratio;
                       c = CLAMP (w1 * w, 0.0, 1.0);
                       color.r += c;
                       dest[0] = CLAMP (color.r*255.0, 0, 255);
                       /* green */
                       spokecol = (gdouble)spokecolor[i                   ].g * (1.0-t) +
                                  (gdouble)spokecolor[(i+1) % pvals.nspoke].g * t;
                       if (w>1.0)
                         color.g = CLAMP (spokecol * w, 0.0, 1.0);
                       else
                         color.g = src[1]/255.0 * compl_ratio + spokecol * ratio;
                       c = CLAMP (w1 * w, 0.0, 1.0);
                       color.g += c;
                       dest[1] = CLAMP (color.g*255.0, 0, 255);
                       /* blue */
                       spokecol = (gdouble)spokecolor[i                   ].b * (1.0-t) +
                                  (gdouble)spokecolor[(i+1) % pvals.nspoke].b * t;
                       if (w>1.0)
                         color.b = CLAMP (spokecol * w, 0.0, 1.0);
                       else
                         color.b = src[2]/255.0 * compl_ratio + spokecol * ratio;
                       c = CLAMP (w1 * w, 0.0, 1.0);
                       color.b += c;
                       dest[2] = CLAMP (color.b*255.0, 0, 255);
                       break;
                     }

                   if (has_alpha)
                     dest[alpha] = new_alpha * 255.0;

                   src += src_rgn.bpp;
                   dest += dest_rgn.bpp;
                 }

               src_row += src_rgn.rowstride;
               dest_row += dest_rgn.rowstride;
             }

           /* Update progress */
           progress += src_rgn.w * src_rgn.h;
           gimp_progress_update ((gdouble) progress / (gdouble) max_progress);
         }

       gimp_progress_update (1.0);

       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 (spoke);
   g_free (spokecolor);
   g_rand_free (gr);
}
Beispiel #5
0
GList *
gimp_palette_load_aco (const gchar  *filename,
                       GError      **error)
{
  GimpPalette *palette;
  gchar       *palette_name;
  gint         fd;
  gint         format_version;
  gint         number_of_colors;
  gint         i;
  gchar        header[4];
  gchar        color_info[10];
  gchar        format2_preamble[4];
  gint         status;

  g_return_val_if_fail (filename != NULL, NULL);
  g_return_val_if_fail (g_path_is_absolute (filename), NULL);
  g_return_val_if_fail (error == NULL || *error == NULL, NULL);

  fd = g_open (filename, O_RDONLY | _O_BINARY, 0);
  if (! fd)
    {
      g_set_error (error,
                   G_FILE_ERROR, g_file_error_from_errno (errno),
                   _("Could not open '%s' for reading: %s"),
                   gimp_filename_to_utf8 (filename), g_strerror (errno));
      return NULL;
    }

  palette_name = g_filename_display_basename (filename);
  palette = GIMP_PALETTE (gimp_palette_new (palette_name));
  g_free (palette_name);

  status = read(fd, header, sizeof (header));

  if (status < 0)
    {
      close(fd);

      return g_list_prepend (NULL, palette);
    }

  format_version = header[1] + (header[0] << 8);
  number_of_colors = header[3] + (header[2] << 8);

  for (i = 0; i < number_of_colors; i++)
  {
      gint     color_space;
      gint     w, x, y, z;
      gboolean color_ok = FALSE;
      GimpRGB  color;

      read (fd, color_info, sizeof (color_info));

      color_space = color_info[1] + (color_info[0] << 8);

      w = (guchar) color_info[3] + ((guchar) color_info[2] << 8);
      x = (guchar) color_info[5] + ((guchar) color_info[4] << 8);
      y = (guchar) color_info[7] + ((guchar) color_info[6] << 8);
      z = (guchar) color_info[9] + ((guchar) color_info[8] << 8);

      if (color_space == 0) /* RGB */
	{
	  gdouble R = ((gdouble) w) / 65536.0;
	  gdouble G = ((gdouble) x) / 65536.0;
	  gdouble B = ((gdouble) y) / 65536.0;

	  gimp_rgba_set (&color, R, G, B, 1.0);

	  color_ok = TRUE;
	}
      else if (color_space == 1) /* HSV */
	{
	  GimpHSV hsv;

	  gdouble H = ((gdouble) w) / 65536.0;
	  gdouble S = ((gdouble) x) / 65536.0;
	  gdouble V = ((gdouble) y) / 65536.0;

	  gimp_hsva_set (&hsv, H, S, V, 1.0);
	  gimp_hsv_to_rgb (&hsv, &color);

	  color_ok = TRUE;
	}
      else if (color_space == 2) /* CMYK */
	{
	  GimpCMYK cmyk;

	  gdouble C = 1.0 - (((gdouble) w) / 65536.0);
	  gdouble M = 1.0 - (((gdouble) x) / 65536.0);
	  gdouble Y = 1.0 - (((gdouble) y) / 65536.0);
	  gdouble K = 1.0 - (((gdouble) z) / 65536.0);

	  gimp_cmyka_set (&cmyk, C, M, Y, K, 1.0);
	  gimp_cmyk_to_rgb (&cmyk, &color);

	  color_ok = TRUE;
	}
      else if (color_space == 8) /* Grayscale */
	{
	  gdouble K = 1.0 - (((gdouble) w) / 10000.0);

	  gimp_rgba_set (&color, K, K, K, 1.0);

	  color_ok = TRUE;
	}
      else if (color_space == 9) /* Wide? CMYK */
	{
	  GimpCMYK cmyk;

	  gdouble C = 1.0 - (((gdouble) w) / 10000.0);
	  gdouble M = 1.0 - (((gdouble) x) / 10000.0);
	  gdouble Y = 1.0 - (((gdouble) y) / 10000.0);
	  gdouble K = 1.0 - (((gdouble) z) / 10000.0);

	  gimp_cmyka_set (&cmyk, C, M, Y, K, 1.0);
	  gimp_cmyk_to_rgb (&cmyk, &color);

	  color_ok = TRUE;
	}
      else
	{
	  g_printerr ("Unsupported color space (%d) in ACO file %s\n",
                      color_space, gimp_filename_to_utf8 (filename));
	}

      if (format_version == 2)
	{
	  gint number_of_chars;

	  read (fd, format2_preamble, sizeof (format2_preamble));
	  number_of_chars = format2_preamble[3] + (format2_preamble[2] << 8);
	  lseek (fd, number_of_chars * 2, SEEK_SET);
	}

      if (color_ok)
        gimp_palette_add_entry (palette, -1, NULL, &color);
  }

  close(fd);

  return g_list_prepend (NULL, palette);
}