1 /* This file is an image processing operation for GEGL 2 * 3 * GEGL is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU Lesser General Public 5 * License as published by the Free Software Foundation; either 6 * version 3 of the License, or (at your option) any later version. 7 * 8 * GEGL is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * 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 * Copyright 2006 Øyvind Kolås <pippin@gimp.org> 17 */ 18 19 20 #include "config.h" 21 #include <glib/gi18n-lib.h> 22 23 #define EPSILON 1e-6 24 25 #ifdef GEGL_PROPERTIES 26 27 property_double (in_low, _("Low input"), 0.0) 28 description ( _("Input luminance level to become lowest output")) 29 ui_range (0.0, 1.0) 30 31 property_double (in_high, _("High input"), 1.0) 32 description (_("Input luminance level to become white")) 33 ui_range (0.0, 1.0) 34 35 property_double (out_low, _("Low output"), 0.0) 36 description (_("Lowest luminance level in output")) 37 ui_range (0.0, 1.0) 38 39 property_double (out_high, _("High output"), 1.0) 40 description (_("Highest luminance level in output")) 41 ui_range (0.0, 1.0) 42 43 #else 44 45 #define GEGL_OP_POINT_FILTER 46 #define GEGL_OP_NAME levels 47 #define GEGL_OP_C_SOURCE levels.c 48 49 #include "gegl-op.h" 50 51 /* GeglOperationPointFilter gives us a linear buffer to operate on 52 * in our requested pixel format 53 */ 54 static gboolean 55 process (GeglOperation *op, 56 void *in_buf, 57 void *out_buf, 58 glong n_pixels, 59 const GeglRectangle *roi, 60 gint level) 61 { 62 GeglProperties *o = GEGL_PROPERTIES (op); 63 gfloat *in_pixel; 64 gfloat *out_pixel; 65 gfloat in_range; 66 gfloat out_range; 67 gfloat in_offset; 68 gfloat out_offset; 69 gfloat scale; 70 glong i; 71 72 in_pixel = in_buf; 73 out_pixel = out_buf; 74 75 in_offset = o->in_low * 1.0; 76 out_offset = o->out_low * 1.0; 77 in_range = o->in_high-o->in_low; 78 out_range = o->out_high-o->out_low; 79 80 if (fabsf (in_range) <= EPSILON) 81 in_range = copysignf (EPSILON, in_range); 82 83 scale = out_range/in_range; 84 85 for (i=0; i<n_pixels; i++) 86 { 87 int c; 88 for (c=0;c<3;c++) 89 out_pixel[c] = (in_pixel[c]- in_offset) * scale + out_offset; 90 out_pixel[3] = in_pixel[3]; 91 out_pixel += 4; 92 in_pixel += 4; 93 } 94 return TRUE; 95 } 96 97 #include "opencl/gegl-cl.h" 98 99 #include "opencl/levels.cl.h" 100 101 static GeglClRunData *cl_data = NULL; 102 103 /* OpenCL processing function */ 104 static gboolean 105 cl_process (GeglOperation *op, 106 cl_mem in_tex, 107 cl_mem out_tex, 108 size_t global_worksize, 109 const GeglRectangle *roi, 110 gint level) 111 { 112 /* Retrieve a pointer to GeglProperties structure which contains all the 113 * chanted properties 114 */ 115 116 GeglProperties *o = GEGL_PROPERTIES (op); 117 118 gfloat in_range; 119 gfloat out_range; 120 gfloat in_offset; 121 gfloat out_offset; 122 gfloat scale; 123 124 cl_int cl_err = 0; 125 126 in_offset = o->in_low * 1.0; 127 out_offset = o->out_low * 1.0; 128 in_range = o->in_high-o->in_low; 129 out_range = o->out_high-o->out_low; 130 131 if (in_range == 0.0) 132 in_range = 0.00000001; 133 134 scale = out_range/in_range; 135 136 if (!cl_data) 137 { 138 const char *kernel_name[] = {"kernel_levels", NULL}; 139 cl_data = gegl_cl_compile_and_build (levels_cl_source, kernel_name); 140 } 141 if (!cl_data) return TRUE; 142 143 cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 0, sizeof(cl_mem), (void*)&in_tex); 144 CL_CHECK; 145 cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 1, sizeof(cl_mem), (void*)&out_tex); 146 CL_CHECK; 147 cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 2, sizeof(cl_float), (void*)&in_offset); 148 CL_CHECK; 149 cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 3, sizeof(cl_float), (void*)&out_offset); 150 CL_CHECK; 151 cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 4, sizeof(cl_float), (void*)&scale); 152 CL_CHECK; 153 154 cl_err = gegl_clEnqueueNDRangeKernel(gegl_cl_get_command_queue (), 155 cl_data->kernel[0], 1, 156 NULL, &global_worksize, NULL, 157 0, NULL, NULL); 158 CL_CHECK; 159 160 return FALSE; 161 162 error: 163 return TRUE; 164 } 165 166 167 168 static void 169 gegl_op_class_init (GeglOpClass *klass) 170 { 171 GeglOperationClass *operation_class; 172 GeglOperationPointFilterClass *point_filter_class; 173 gchar *composition = 174 "<?xml version='1.0' encoding='UTF-8'?>" 175 "<gegl>" 176 " <node operation='gegl:crop' width='200' height='200'/>" 177 " <node operation='gegl:over'>" 178 " <node operation='gegl:levels'>" 179 " <params>" 180 " <param name='in-low'>0.54</param>" 181 " <param name='in-high'>0.60</param>" 182 " <param name='out-low'>0.57</param>" 183 " <param name='out-high'>0.68</param>" 184 " </params>" 185 " </node>" 186 " <node operation='gegl:load' path='standard-input.png'/>" 187 " </node>" 188 " <node operation='gegl:checkerboard'>" 189 " <params>" 190 " <param name='color1'>rgb(0.25,0.25,0.25)</param>" 191 " <param name='color2'>rgb(0.75,0.75,0.75)</param>" 192 " </params>" 193 " </node>" 194 "</gegl>"; 195 196 operation_class = GEGL_OPERATION_CLASS (klass); 197 point_filter_class = GEGL_OPERATION_POINT_FILTER_CLASS (klass); 198 199 point_filter_class->process = process; 200 point_filter_class->cl_process = cl_process; 201 202 operation_class->opencl_support = TRUE; 203 204 gegl_operation_class_set_keys (operation_class, 205 "name", "gegl:levels", 206 "title", _("Levels"), 207 "categories" , "color", 208 "description", _("Remaps the intensity range of the image"), 209 "reference-hash", "b26ace9ce32e98b8ffa2a57f10a42e0d", 210 "reference-composition", composition, 211 NULL); 212 } 213 214 #endif 215