levels.c 5.76 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 2006 Øyvind Kolås <pippin@gimp.org>
 */

19 20 21 22 23

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


24 25
#ifdef GEGL_PROPERTIES

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
property_double (in_low, _("Low input"), 0.0)
    description ( _("Input luminance level to become lowest output"))
    value_range (-1.0, 4.0)
    ui_range    (0.0, 1.0)

property_double (in_high, _("High input"), 1.0)
    description (_("Input luminance level to become white"))
    value_range (-1.0, 4.0)
    ui_range    (0.0, 1.0)

property_double (out_low, _("Low output"), 0.0)
    description (_("Lowest luminance level in output"))
    value_range (-1.0, 4.0)
    ui_range    (0.0, 1.0)

property_double (out_high, _("High output"), 1.0)
    description (_("Highest luminance level in output"))
    value_range (-1.0, 4.0)
    ui_range    (0.0, 1.0)
45 46 47

#else

48
#define GEGL_OP_POINT_FILTER
49
#define GEGL_OP_NAME     levels
50
#define GEGL_OP_C_SOURCE levels.c
51

52
#include "gegl-op.h"
53 54 55 56 57

/* GeglOperationPointFilter gives us a linear buffer to operate on
 * in our requested pixel format
 */
static gboolean
58 59 60 61
process (GeglOperation       *op,
         void                *in_buf,
         void                *out_buf,
         glong                n_pixels,
62 63
         const GeglRectangle *roi,
         gint                 level)
64
{
65
  GeglProperties *o = GEGL_PROPERTIES (op);
66 67
  gfloat     *in_pixel;
  gfloat     *out_pixel;
68 69 70 71 72 73 74
  gfloat      in_range;
  gfloat      out_range;
  gfloat      in_offset;
  gfloat      out_offset;
  gfloat      scale;
  glong       i;

75 76
  in_pixel = in_buf;
  out_pixel = out_buf;
77

78 79 80 81
  in_offset = o->in_low * 1.0;
  out_offset = o->out_low * 1.0;
  in_range = o->in_high-o->in_low;
  out_range = o->out_high-o->out_low;
82 83 84

  if (in_range == 0.0)
    in_range = 0.00000001;
85

86 87 88 89 90 91
  scale = out_range/in_range;

  for (i=0; i<n_pixels; i++)
    {
      int c;
      for (c=0;c<3;c++)
92 93 94 95
        out_pixel[c] = (in_pixel[c]- in_offset) * scale + out_offset;
      out_pixel[3] = in_pixel[3];
      out_pixel += 4;
      in_pixel += 4;
96 97 98 99
    }
  return TRUE;
}

100 101
#include "opencl/gegl-cl.h"

Victor Oliveira's avatar
Victor Oliveira committed
102
#include "opencl/levels.cl.h"
103

104
static GeglClRunData *cl_data = NULL;
105 106

/* OpenCL processing function */
Victor Oliveira's avatar
Victor Oliveira committed
107
static gboolean
108 109 110 111 112 113 114
cl_process (GeglOperation       *op,
            cl_mem               in_tex,
            cl_mem               out_tex,
            size_t               global_worksize,
            const GeglRectangle *roi,
            gint                 level)
{
115
  /* Retrieve a pointer to GeglProperties structure which contains all the
116 117 118
   * chanted properties
   */

119
  GeglProperties *o = GEGL_PROPERTIES (op);
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141

  gfloat      in_range;
  gfloat      out_range;
  gfloat      in_offset;
  gfloat      out_offset;
  gfloat      scale;

  cl_int cl_err = 0;

  in_offset = o->in_low * 1.0;
  out_offset = o->out_low * 1.0;
  in_range = o->in_high-o->in_low;
  out_range = o->out_high-o->out_low;

  if (in_range == 0.0)
    in_range = 0.00000001;

  scale = out_range/in_range;

  if (!cl_data)
    {
      const char *kernel_name[] = {"kernel_levels", NULL};
Victor Oliveira's avatar
Victor Oliveira committed
142
      cl_data = gegl_cl_compile_and_build (levels_cl_source, kernel_name);
143
    }
Victor Oliveira's avatar
Victor Oliveira committed
144 145 146 147 148 149 150 151 152 153 154 155
  if (!cl_data) return TRUE;

  cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 0, sizeof(cl_mem),   (void*)&in_tex);
  CL_CHECK;
  cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 1, sizeof(cl_mem),   (void*)&out_tex);
  CL_CHECK;
  cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 2, sizeof(cl_float), (void*)&in_offset);
  CL_CHECK;
  cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 3, sizeof(cl_float), (void*)&out_offset);
  CL_CHECK;
  cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 4, sizeof(cl_float), (void*)&scale);
  CL_CHECK;
156 157 158 159 160

  cl_err = gegl_clEnqueueNDRangeKernel(gegl_cl_get_command_queue (),
                                        cl_data->kernel[0], 1,
                                        NULL, &global_worksize, NULL,
                                        0, NULL, NULL);
Victor Oliveira's avatar
Victor Oliveira committed
161
  CL_CHECK;
162

Victor Oliveira's avatar
Victor Oliveira committed
163 164 165 166
  return FALSE;

error:
  return TRUE;
167 168 169
}


170 171

static void
172
gegl_op_class_init (GeglOpClass *klass)
173 174 175
{
  GeglOperationClass            *operation_class;
  GeglOperationPointFilterClass *point_filter_class;
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
  gchar                         *composition = "<?xml version='1.0' encoding='UTF-8'?>"
    "<gegl>"
    "<node operation='gegl:levels'>"
    "  <params>"
    "    <param name='in-low'>0.54</param>"
    "    <param name='in-high'>0.60</param>"
    "    <param name='out-low'>0.57</param>"
    "    <param name='out-high'>0.68</param>"
    "  </params>"
    "</node>"
    "<node operation='gegl:load'>"
    "  <params>"
    "    <param name='path'>standard-input.png</param>"
    "  </params>"
    "</node>"
    "</gegl>";
192 193 194 195 196

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

  point_filter_class->process = process;
197 198 199
  point_filter_class->cl_process = cl_process;

  operation_class->opencl_support = TRUE;
200

201
  gegl_operation_class_set_keys (operation_class,
202 203
    "name",        "gegl:levels",
    "title",       _("Levels"),
204 205
    "categories" , "color",
    "description", _("Remaps the intensity range of the image"),
206
    "reference-hash", "52e9dca541181f09f6cfac68afe987a2",
207
    "reference-composition", composition,
208
    NULL);
209 210
}

211
#endif