1 /* This file is an image processing operation for GEGL 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation; either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * This program 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 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <https://www.gnu.org/licenses/>. 15 * 16 * 17 * Exchange one color with the other (settable threshold to convert from 18 * one color-shade to another...might do wonders on certain images, or be 19 * totally useless on others). 20 * 21 * Author: Adam D. Moss <adam@foxbox.org> 22 * 23 * GEGL port: Thomas Manni <thomas.manni@free.fr> 24 * 25 */ 26 27 #include "config.h" 28 #include <glib/gi18n-lib.h> 29 30 #ifdef GEGL_PROPERTIES 31 32 enum_start (gegl_video_degradation_type) 33 enum_value (GEGL_VIDEO_DEGRADATION_TYPE_STAGGERED, "staggered", 34 N_("Staggered")) 35 enum_value (GEGL_VIDEO_DEGRADATION_TYPE_LARGE_STAGGERED, "large-staggered", 36 N_("Large staggered")) 37 enum_value (GEGL_VIDEO_DEGRADATION_TYPE_STRIPED, "striped", 38 N_("Striped")) 39 enum_value (GEGL_VIDEO_DEGRADATION_TYPE_WIDE_STRIPED, "wide-striped", 40 N_("Wide striped")) 41 enum_value (GEGL_VIDEO_DEGRADATION_TYPE_LONG_STAGGERED, "long-staggered", 42 N_("Long staggered")) 43 enum_value (GEGL_VIDEO_DEGRADATION_TYPE_3X3, "3x3", 44 N_("3x3")) 45 enum_value (GEGL_VIDEO_DEGRADATION_TYPE_LARGE_3X3, "large-3x3", 46 N_("Large 3x3")) 47 enum_value (GEGL_VIDEO_DEGRADATION_TYPE_Hex, "hex", 48 N_("Hex")) 49 enum_value (GEGL_VIDEO_DEGRADATION_TYPE_DOTS, "dots", 50 N_("Dots")) 51 enum_end (GeglVideoDegradationType) 52 53 property_enum (pattern, _("Pattern"), GeglVideoDegradationType, 54 gegl_video_degradation_type, 55 GEGL_VIDEO_DEGRADATION_TYPE_STRIPED) 56 description (_("Type of RGB pattern to use")) 57 58 property_boolean (additive, _("Additive"), TRUE) 59 description(_("Whether the function adds the result to the original image.")) 60 61 property_boolean (rotated, _("Rotated"), FALSE) 62 description(_("Whether to rotate the RGB pattern by ninety degrees.")) 63 64 #else 65 66 #define GEGL_OP_POINT_FILTER 67 #define GEGL_OP_NAME video_degradation 68 #define GEGL_OP_C_SOURCE video-degradation.c 69 70 #include "gegl-op.h" 71 72 #define MAX_PATTERNS 9 73 #define MAX_PATTERN_SIZE 108 74 75 static const gint pattern_width[MAX_PATTERNS] = { 2, 4, 1, 1, 2, 3, 6, 6, 5 }; 76 static const gint pattern_height[MAX_PATTERNS] = { 6, 12, 3, 6, 12, 3, 6, 77 18, 15 }; 78 79 static const gint pattern[MAX_PATTERNS][MAX_PATTERN_SIZE] = 80 { 81 { 82 0, 1, 83 0, 2, 84 1, 2, 85 1, 0, 86 2, 0, 87 2, 1, 88 }, 89 { 90 0, 0, 1, 1, 91 0, 0, 1, 1, 92 0, 0, 2, 2, 93 0, 0, 2, 2, 94 1, 1, 2, 2, 95 1, 1, 2, 2, 96 1, 1, 0, 0, 97 1, 1, 0, 0, 98 2, 2, 0, 0, 99 2, 2, 0, 0, 100 2, 2, 1, 1, 101 2, 2, 1, 1, 102 }, 103 { 104 0, 105 1, 106 2, 107 }, 108 { 109 0, 110 0, 111 1, 112 1, 113 2, 114 2, 115 }, 116 { 117 0, 1, 118 0, 1, 119 0, 2, 120 0, 2, 121 1, 2, 122 1, 2, 123 1, 0, 124 1, 0, 125 2, 0, 126 2, 0, 127 2, 1, 128 2, 1, 129 }, 130 { 131 0, 1, 2, 132 2, 0, 1, 133 1, 2, 0, 134 }, 135 { 136 0, 0, 1, 1, 2, 2, 137 0, 0, 1, 1, 2, 2, 138 2, 2, 0, 0, 1, 1, 139 2, 2, 0, 0, 1, 1, 140 1, 1, 2, 2, 0, 0, 141 1, 1, 2, 2, 0, 0, 142 }, 143 { 144 2, 2, 0, 0, 0, 0, 145 2, 2, 2, 0, 0, 2, 146 2, 2, 2, 2, 2, 2, 147 2, 2, 2, 1, 1, 2, 148 2, 2, 1, 1, 1, 1, 149 1, 1, 1, 1, 1, 1, 150 0, 0, 1, 1, 1, 1, 151 0, 0, 0, 1, 1, 0, 152 0, 0, 0, 0, 0, 0, 153 0, 0, 0, 2, 2, 0, 154 0, 0, 2, 2, 2, 2, 155 2, 2, 2, 2, 2, 2, 156 1, 1, 2, 2, 2, 2, 157 1, 1, 1, 2, 2, 1, 158 1, 1, 1, 1, 1, 1, 159 1, 1, 1, 0, 0, 1, 160 1, 1, 0, 0, 0, 0, 161 0, 0, 0, 0, 0, 0, 162 }, 163 { 164 0, 1, 2, 0, 0, 165 1, 1, 1, 2, 0, 166 0, 1, 2, 2, 2, 167 0, 0, 1, 2, 0, 168 0, 1, 1, 1, 2, 169 2, 0, 1, 2, 2, 170 0, 0, 0, 1, 2, 171 2, 0, 1, 1, 1, 172 2, 2, 0, 1, 2, 173 2, 0, 0, 0, 1, 174 1, 2, 0, 1, 1, 175 2, 2, 2, 0, 1, 176 1, 2, 0, 0, 0, 177 1, 1, 2, 0, 1, 178 1, 2, 2, 2, 0, 179 } 180 }; 181 182 static void 183 prepare (GeglOperation *operation) 184 { 185 const Babl *format = babl_format_with_space ("R'G'B'A float", gegl_operation_get_source_space (operation, "input")); 186 187 gegl_operation_set_format (operation, "input", format); 188 gegl_operation_set_format (operation, "output", format); 189 } 190 191 static gboolean 192 cl_process (GeglOperation *operation, 193 cl_mem in_buf, 194 cl_mem out_buf, 195 const size_t n_pixels, 196 const GeglRectangle *roi, 197 gint level) 198 { 199 GeglOperationClass *operation_class = GEGL_OPERATION_GET_CLASS (operation); 200 GeglClRunData *cl_data = operation_class->cl_data; 201 GeglProperties *o = GEGL_PROPERTIES (operation); 202 const size_t gbl_size[2] = {roi->width, roi->height}; 203 const size_t gbl_off[2] = {roi->x, roi->y}; 204 cl_int cl_err = 0; 205 cl_mem filter_pat = NULL; 206 207 if (!cl_data) 208 goto error; 209 filter_pat = gegl_clCreateBuffer (gegl_cl_get_context (), 210 CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, 211 pattern_width[o->pattern] * 212 pattern_height[o->pattern] * sizeof(cl_int), 213 (void*)pattern[o->pattern], 214 &cl_err); 215 CL_CHECK; 216 cl_err = gegl_cl_set_kernel_args (cl_data->kernel[0], 217 sizeof(cl_mem), &in_buf, 218 sizeof(cl_mem), &out_buf, 219 sizeof(cl_mem), &filter_pat, 220 sizeof(cl_int), &pattern_width[o->pattern], 221 sizeof(cl_int), &pattern_height[o->pattern], 222 sizeof(cl_int), &o->additive, 223 sizeof(cl_int), &o->rotated, 224 NULL); 225 CL_CHECK; 226 cl_err = gegl_clEnqueueNDRangeKernel (gegl_cl_get_command_queue (), 227 cl_data->kernel[0], 2, 228 gbl_off, gbl_size, NULL, 229 0, NULL, NULL); 230 CL_CHECK; 231 cl_err = gegl_clFinish (gegl_cl_get_command_queue ()); 232 CL_CHECK; 233 cl_err = gegl_clReleaseMemObject (filter_pat); 234 CL_CHECK; 235 return FALSE; 236 error: 237 if (filter_pat) 238 gegl_clReleaseMemObject (filter_pat); 239 return TRUE; 240 } 241 242 static gboolean 243 process (GeglOperation *operation, 244 void *in_buf, 245 void *out_buf, 246 glong n_pixels, 247 const GeglRectangle *roi, 248 gint level) 249 { 250 GeglProperties *o = GEGL_PROPERTIES (operation); 251 gfloat *input = in_buf; 252 gfloat *output = out_buf; 253 gfloat value; 254 gint x, y; 255 gint real_x, real_y; 256 gint b; 257 gint sel_b; 258 gint idx; 259 260 for (y = 0 ; y < roi->height ; y++) 261 { 262 real_y = roi->y + y; 263 for (x = 0 ; x < roi->width ; x++) 264 { 265 real_x = roi->x + x; 266 267 if (o->rotated) 268 { 269 sel_b = pattern[o->pattern][pattern_width[o->pattern]* 270 (real_x % pattern_height[o->pattern]) + 271 real_y % pattern_width[o->pattern] ]; 272 } 273 else 274 { 275 sel_b = pattern[o->pattern][pattern_width[o->pattern]* 276 (real_y % pattern_height[o->pattern]) + 277 real_x % pattern_width[o->pattern] ]; 278 } 279 280 for (b = 0; b < 4; b++) 281 { 282 idx = (x + y * roi->width) * 4 + b; 283 if (b < 3 ) 284 { 285 value = (sel_b == b) ? input[idx] : 0.f; 286 if (o->additive) 287 { 288 gfloat temp = value + input[idx]; 289 value = MIN (temp, 1.0); 290 } 291 output[idx] = value; 292 } 293 else 294 { 295 output[idx] = input[idx]; 296 } 297 } 298 } 299 } 300 301 return TRUE; 302 } 303 304 #include "opencl/video-degradation.cl.h" 305 306 static void 307 gegl_op_class_init (GeglOpClass *klass) 308 { 309 GeglOperationClass *operation_class; 310 GeglOperationPointFilterClass *filter_class; 311 312 operation_class = GEGL_OPERATION_CLASS (klass); 313 filter_class = GEGL_OPERATION_POINT_FILTER_CLASS (klass); 314 315 operation_class->prepare = prepare; 316 317 filter_class->process = process; 318 filter_class->cl_process = cl_process; 319 320 gegl_operation_class_set_keys (operation_class, 321 "name", "gegl:video-degradation", 322 "title", _("Video Degradation"), 323 "categories", "distort", 324 "license", "GPL3+", 325 "reference-hash", "1f7ad41dc1c0595b9b90ad1f72e18d2f", 326 "description", _("This function simulates the degradation of " 327 "being on an old low-dotpitch RGB video monitor."), 328 "cl-source" , video_degradation_cl_source, 329 NULL); 330 } 331 332 #endif 333