New to GEGL, and HSL plugin

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I'm a college student, and don't know a whole lot about GEGL, or image processing, in general, but would like to get into it, a bit, and maybe to help hasten along the arrival of the next-generation Gimp or whatever.  With that in mind, I'm starting to feel my way around the codebase, in hopes of being able to make some useful contributions.

As a getting-started project, I wrote a rough hue/saturation/lightness adjustment operation, which I've attached, and was hoping maybe I could get some feedback on it, to see if I'm getting the write idea about this task, in particular, and about the "GEGL way of doing things," in general.  A few specific questions:

* In the operation, I convert from 32-bit float rgba to HSL, do the operations, and convert back again.  It occured to me, later, that perhaps this was something that should be done as a colorspace conversion in babl, instead, though it doesn't look like HSL is a currently supported babl colorspace.  Is that correct, or is this legit?

* Are adjustments to lightness and saturation usually multiplicative?  I started out having all of the adjustments be additive, and while that worked for hue, it gave results for lightness and saturation that were markedly different from those of the current Gimp.  At present, they add the factor times the current value, and that seems to approximate the Gimp's behavior for saturation, though not for lightness.  Perhaps I just don't have the minimum and maximum values of my ranges set appropriately?  I may just dig into the current Gimp code and see how they do it...

* Is there a standard for coding style in GEGL?  It seems that two-space indents are common, but other than that, other practices don't seem entirely consistent, and I'd like to format things appropriately, as I go, if possible.

* Is there a TODO, somewhere?  I saw that one existed in earlier CVS iterations, but it seems to be gone from current SVN.  I picked HSL because I figured it wouldn't be too hard, and there wasn't one, but being able to spend time on things that actually need doing would be good.

Thanks,
Andrew
/* This file is an image processing operation for GEGL
 *
 * GEGL is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * GEGL is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with GEGL; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 * Copyright 2007 Andrew Pendleton
 */
#if GEGL_CHANT_PROPERTIES

gegl_chant_double (hue,      -180.0, 180.0, 0.0,
   "Amount to adjust hue (in degrees)")
gegl_chant_double (saturation,    -1.0,  1.0, 0.0,
   "Amount to adjust saturation")
gegl_chant_double (lightness,    -1.0,  1.0, 0.0,
   "Amount to adjust lightness")

#else

#define GEGL_CHANT_POINT_FILTER
#define GEGL_CHANT_NAME          hsl
#define GEGL_CHANT_DESCRIPTION   "Adjusts the hue, saturation, and/or lightness of the image"
#define GEGL_CHANT_SELF          "hsl.c"
#define GEGL_CHANT_CATEGORIES    "color"
#define GEGL_CHANT_INIT
#include "gegl-chant.h"

static void init (GeglChantOperation *self)
{
  /* set the babl format this operation prefers to work on */
  GEGL_OPERATION_POINT_FILTER (self)->format = babl_format ("RGBA float");
}

static gboolean
process (GeglOperation *op,
         void          *in_buf,
         void          *out_buf,
         glong          samples) 
{
  gint i;
  gfloat *in  = in_buf;
  gfloat *out = out_buf;
  GeglChantOperation *self;
  
  self = GEGL_CHANT_OPERATION (op);
  
  /* formulas for this implementation were obtained from
    http://en.wikipedia.org/wiki/HLS_color_space */
  
  for (i=0; i<samples; i++)
    {
      
      gfloat r, g, b, h, s, l, a, max, min, t1, t2, t3r, t3g, t3b;
      r = in[0];
      g = in[1];
      b = in[2];
      a = in[3];
      
      /* find min and max of the RGB values */
      if (r > g)
      {
        if (r > b)
        {
          max = r;
          if (b > g)
          {
            min = g;
          }
          else
          {
            min = b;
          }
        }
        else
        {
          max = b;
          min = g;
        }
      }
      else
      {
        if (b > r)
        {
          min = r;
          if (b > g)
          {
            max = b;
          }
          else
          {
            max = g;
          }
        }
        else
        {
          max = g;
          min = r;
        }
      }
      
      /* convert to hsl */
      if (max == min)
      {
        h = 0;
      }
      else if (max == r)
      {
        h = (g - b) / (max - min);
        if (g < b)
        {
          h += 6;
        }
      }
      else if (max == g)
      {
        h = (b - r) / (max - min) + 2;
      }
      else
      {
        h = (r - g) / (max - min) + 4;
      }
      
      l = 0.5 * (max + min);
      
      if (l == 0 || max == min)
      {
        s = 0;
      }
      else if (0 < l && l <= 0.5)
      {
        s = (max - min) / (2 * l);
      }
      else
      {
        s = (max - min) / (2 - 2 * l);
      }
      
      /* adjust the HSL values based on input */
      h += (self->hue / 60);
      s += self->saturation * s;
      l += self->lightness * l;
      
      /* check that values are within range */
      if (h >= 6) h -= 6;
      if (h < 0) h += 6;
      if (s > 1) s = 1;
      if (s < 0) s = 0;
      if (l > 1) l = 1;
      if (l < 0) l = 0;
      
      /* convert back to rgb */
      t2 = (l < 0.5 ? l * (1.0 + s) : l + s - (l * s));
      t1 = (2 * l - t2);
      
      t3r = h + 2;
      t3g = h;
      t3b = h - 2;
      
      if (t3r < 0) t3r += 6;
      if (t3b < 0) t3b += 6;
      if (t3r > 6) t3r -= 6;
      if (t3b > 6) t3b -= 6;
      
      if (t3r < 1)
      {
        r = t1 + ((t2 - t1) * t3r);
      }
      else if (1 <= t3r && t3r < 3)
      {
        r = t2;
      }
      else if (3 <= t3r && t3r < 4)
      {
        r = t1 + ((t2 - t1) * (4 - t3r));
      }
      else
      {
        r = t1;
      }
      
      if (t3g < 1)
      {
        g = t1 + ((t2 - t1) * t3g);
      }
      else if (1 <= t3g && t3g < 3)
      {
        g = t2;
      }
      else if (3 <= t3g && t3g < 4)
      {
        g = t1 + ((t2 - t1) * (4 - t3g));
      }
      else
      {
        g = t1;
      }
      
      if (t3b < 1)
      {
        b = t1 + ((t2 - t1) * t3b);
      }
      else if (1 <= t3b && t3b < 3)
      {
        b = t2;
      }
      else if (3 <= t3b && t3b < 4)
      {
        b = t1 + ((t2 - t1) * (4 - t3b));
      }
      else
      {
        b = t1;
      }
      
      out[0] = r;
      out[1] = g;
      out[2] = b;
      
      out[3]=in[3];
      in += 4;
      out+= 4;
    }
  return TRUE;
}

#endif
_______________________________________________
Gegl-developer mailing list
Gegl-developer@xxxxxxxxxxxxxxxxxxxxxx
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer

[Index of Archives]     [Yosemite News]     [Yosemite Photos]     [gtk]     [GIMP Users]     [KDE]     [Gimp's Home]     [Gimp on Windows]     [Steve's Art]

  Powered by Linux