value-invert.c 4.15 KB
Newer Older
1 2 3 4 5
/* 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
6
 * version 3 of the License, or (at your option) any later version.
7 8 9 10 11 12 13
 *
 * 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
14
 * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
15 16 17 18
 *
 * Copyright 2007 Mukund Sivaraman <muks@mukund.org>
 */

19 20 21 22 23 24
/* XXX
 * This plug-in isn't really useful apart for compatibility with GIMP
 * scripts, operating with HSV as a color model for filters isn't really
 * useful.
 */

25 26 27 28 29 30 31 32 33 34 35 36 37 38
/*
 * The plug-in only does v = 1.0 - v; for each pixel in the image, or
 * each entry in the colormap depending upon the type of image, where 'v'
 * is the value in HSV color model.
 *
 * The plug-in code is optimized towards this, in that it is not a full
 * RGB->HSV->RGB transform, but shortcuts many of the calculations to
 * effectively only do v = 1.0 - v. In fact, hue is never calculated. The
 * shortcuts can be derived from running a set of r, g, b values through the
 * RGB->HSV transform and then from HSV->RGB and solving out the redundant
 * portions.
 *
 */

39 40 41 42

#include "config.h"
#include <glib/gi18n-lib.h>

43
#ifdef GEGL_PROPERTIES
44

45
   /* no properties */
46

47 48
#else

49
#define GEGL_OP_POINT_FILTER
50
#define GEGL_OP_NAME     value_invert
51
#define GEGL_OP_C_SOURCE value-invert.c
52

53
#include "gegl-op.h"
54

55 56 57
static void
prepare (GeglOperation *operation)
{
58 59 60
  const Babl *space = gegl_operation_get_source_space (operation, "input");
  gegl_operation_set_format (operation, "input", babl_format_with_space ("R'G'B'A float", space));
  gegl_operation_set_format (operation, "output", babl_format_with_space ("R'G'B'A float", space));
61 62
}

63
static gboolean
64 65 66 67
process (GeglOperation       *op,
         void                *in_buf,
         void                *out_buf,
         glong                samples,
68 69
         const GeglRectangle *roi,
         gint                 level)
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
{
  glong   j;
  gfloat *src  = in_buf;
  gfloat *dest = out_buf;
  gfloat  r, g, b;
  gfloat  value, min;
  gfloat  delta;

  for (j = 0; j < samples; j++)
    {
      r = *src++;
      g = *src++;
      b = *src++;

      if (r > g)
        {
          value = MAX (r, b);
          min = MIN (g, b);
        }
      else
        {
          value = MAX (g, b);
          min = MIN (r, b);
        }

      delta = value - min;
      if ((value == 0) || (delta == 0))
        {
          r = 1.0 - value;
          g = 1.0 - value;
          b = 1.0 - value;
        }
      else
        {
          if (r == value)
            {
              r = 1.0 - r;
107 108
              b = r * b / value;
              g = r * g / value;
109 110 111 112
            }
          else if (g == value)
            {
              g = 1.0 - g;
113 114
              r = g * r / value;
              b = g * b / value;
115 116 117 118
            }
          else
            {
              b = 1.0 - b;
119 120
              g = b * g / value;
              r = b * r / value;
121 122 123 124 125 126 127 128 129 130 131 132
            }
        }

      *dest++ = r;
      *dest++ = g;
      *dest++ = b;

      *dest++ = *src++;
    }
  return TRUE;
}

133
#include "opencl/value-invert.cl.h"
134

135
static void
136
gegl_op_class_init (GeglOpClass *klass)
137 138 139 140 141 142 143 144
{
  GeglOperationClass            *operation_class;
  GeglOperationPointFilterClass *point_filter_class;

  operation_class    = GEGL_OPERATION_CLASS (klass);
  point_filter_class = GEGL_OPERATION_POINT_FILTER_CLASS (klass);

  point_filter_class->process = process;
145
  operation_class->prepare = prepare;
146 147

  gegl_operation_class_set_keys (operation_class,
148 149
    "name",        "gegl:value-invert",
    "title",       _("Value Invert"),
150
    "categories" , "color",
151
    "reference-hash", "1457b5c30de7a730a54c80028097e046",
152
    "description",
153 154
        _("Invert the value component, the result has the brightness "
          "inverted, keeping the color."),
155
    "cl-source"  , value_invert_cl_source,
156
    NULL);
157 158
}

159 160
#endif