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 * Copyright 1997 Miles O'Neal <meo@rru.com> http://www.rru.com/~meo/ 17 * Copyright 2012 Maxime Nicco <maxime.nicco@gmail.com> 18 */ 19 20 /* 21 * SLUR Operation 22 * We replace the current pixel by: 23 * 80% chance it's from directly above, 24 * 10% from above left, 25 * 10% from above right. 26 */ 27 28 #include "config.h" 29 30 #include <glib/gi18n-lib.h> 31 32 #ifdef GEGL_PROPERTIES 33 34 property_double (pct_random, _("Randomization (%)"), 50.0) 35 value_range (0.0, 100.0) 36 37 property_int (repeat, _("Repeat"), 1) 38 value_range (1, 100) 39 40 property_seed (seed, _("Random seed"), rand) 41 42 #else 43 44 #define GEGL_OP_AREA_FILTER 45 #define GEGL_OP_NAME noise_slur 46 #define GEGL_OP_C_SOURCE noise-slur.c 47 48 #include "gegl-op.h" 49 50 static void 51 prepare (GeglOperation *operation) 52 { 53 GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation); 54 GeglProperties *o = GEGL_PROPERTIES (operation); 55 const Babl *format; 56 57 op_area->left = 58 op_area->right = 59 op_area->top = o->repeat; 60 op_area->bottom = 0; 61 62 format = gegl_operation_get_source_format (operation, "input"); 63 64 gegl_operation_set_format (operation, "input", format); 65 gegl_operation_set_format (operation, "output", format); 66 } 67 68 /* We avoid unecessary calls to gegl_random 69 * by recomputing a small part ourselves. 70 * see gegl/gegl-random.c for details */ 71 #define RAND_UINT_TO_FLOAT(x) (((x) & 0xffff) * 0.00001525902189669642175) 72 73 static gboolean 74 process (GeglOperation *operation, 75 GeglBuffer *input, 76 GeglBuffer *output, 77 const GeglRectangle *result, 78 gint level) 79 { 80 GeglProperties *o; 81 const Babl *format; 82 gint bpp; 83 GeglBufferIterator *gi; 84 GeglSampler *sampler; 85 86 o = GEGL_PROPERTIES (operation); 87 88 format = gegl_operation_get_source_format (operation, "input"); 89 bpp = babl_format_get_bytes_per_pixel (format); 90 91 gi = gegl_buffer_iterator_new (output, result, 0, format, 92 GEGL_ACCESS_WRITE, GEGL_ABYSS_CLAMP, 1); 93 94 sampler = gegl_buffer_sampler_new_at_level (input, format, GEGL_SAMPLER_NEAREST, level); 95 96 while (gegl_buffer_iterator_next (gi)) 97 { 98 gchar *data = gi->items[0].data; 99 GeglRectangle roi = gi->items[0].roi; 100 gint i, j; 101 102 for (j = roi.y; j < roi.y + roi.height ; j++) 103 for (i = roi.x; i < roi.x + roi.width ; i++) 104 { 105 gint r; 106 gint pos_x = i, pos_y = j; 107 108 for (r = 0; r < o->repeat; r++) 109 { 110 guint rand = gegl_random_int (o->rand, pos_x, pos_y, 0, r); 111 gfloat pct = RAND_UINT_TO_FLOAT (rand) * 100.0; 112 113 if (pct <= o->pct_random) 114 { 115 gint rand2 = (gint) (rand % 10); 116 117 pos_y--; 118 119 switch (rand2) 120 { 121 case 0: 122 pos_x--; 123 break; 124 case 9: 125 pos_x++; 126 break; 127 default: 128 break; 129 } 130 } 131 } 132 133 gegl_sampler_get (sampler, pos_x, pos_y, NULL, data, GEGL_ABYSS_CLAMP); 134 data += bpp; 135 } 136 } 137 138 g_object_unref (sampler); 139 140 return TRUE; 141 } 142 143 static void 144 gegl_op_class_init (GeglOpClass *klass) 145 { 146 GeglOperationClass *operation_class; 147 GeglOperationFilterClass *filter_class; 148 149 operation_class = GEGL_OPERATION_CLASS (klass); 150 filter_class = GEGL_OPERATION_FILTER_CLASS (klass); 151 152 operation_class->prepare = prepare; 153 filter_class->process = process; 154 155 gegl_operation_class_set_keys (operation_class, 156 "name", "gegl:noise-slur", 157 "title", _("Noise Slur"), 158 "categories", "noise", 159 "reference-hash", "8d921285191c7e1bfac09acb7ed67f21", 160 "license", "GPL3+", 161 "description", _("Randomly slide some pixels downward (similar to melting)"), 162 NULL); 163 } 164 165 #endif 166