shift.c 4.33 KB
Newer Older
Hans Lo's avatar
Hans Lo committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/* 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
 * version 3 of the License, or (at your option) any later version.
 *
 * 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
 * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
 *
 * Copyright 1997 Brian Degenhardt <bdegenha@ucsd.edu>
 * Copyright 1997 Federico Mena Quinter <quartic@polloux.fciencias.unam.mx>
 * Copyright 2012 Hans Lo <hansshulo@gmail.com>
 */

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

24
#ifdef GEGL_PROPERTIES
Hans Lo's avatar
Hans Lo committed
25

26
enum_start (gegl_shift_direction)
27 28
  enum_value (GEGL_SHIFT_DIRECTION_HORIZONTAL, "horizontal", N_("Horizontal"))
  enum_value (GEGL_SHIFT_DIRECTION_VERTICAL,   "vertical",   N_("Vertical"))
29
enum_end (GeglShiftDirection)
Hans Lo's avatar
Hans Lo committed
30

31 32 33 34
property_int  (shift, _("Shift"), 5)
    description(_("Maximum amount to shift"))
    value_range (0, 200)
    ui_meta    ("unit", "pixel-distance")
35

36
property_enum (direction, _("Shift direction"),
37
    GeglShiftDirection, gegl_shift_direction,
38
    GEGL_SHIFT_DIRECTION_HORIZONTAL)
Hans Lo's avatar
Hans Lo committed
39

40
property_seed (seed, _("Random seed"), rand)
41

Hans Lo's avatar
Hans Lo committed
42 43
#else

44 45
#define GEGL_OP_AREA_FILTER
#define GEGL_OP_C_FILE "shift.c"
Hans Lo's avatar
Hans Lo committed
46

47
#include "gegl-op.h"
Hans Lo's avatar
Hans Lo committed
48

49 50
static void
prepare (GeglOperation *operation)
Hans Lo's avatar
Hans Lo committed
51
{
52
  GeglProperties          *o       = GEGL_PROPERTIES (operation);
53
  GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation);
54
  const Babl              *format;
55

56
  if (o->direction == GEGL_SHIFT_DIRECTION_HORIZONTAL)
57 58 59 60 61 62
    {
      op_area->left   = o->shift;
      op_area->right  = o->shift;
      op_area->top    = 0;
      op_area->bottom = 0;
    }
63
  else if (o->direction == GEGL_SHIFT_DIRECTION_VERTICAL)
64 65 66 67 68 69
    {
      op_area->top    = o->shift;
      op_area->bottom = o->shift;
      op_area->left   = 0;
      op_area->right  = 0;
    }
Hans Lo's avatar
Hans Lo committed
70

71 72 73 74
  format = gegl_operation_get_source_format (operation, "input");

  gegl_operation_set_format (operation, "input",  format);
  gegl_operation_set_format (operation, "output", format);
Hans Lo's avatar
Hans Lo committed
75 76
}

77

Hans Lo's avatar
Hans Lo committed
78 79 80 81 82 83 84
static gboolean
process (GeglOperation       *operation,
         GeglBuffer          *input,
         GeglBuffer          *output,
         const GeglRectangle *result,
         gint                 level)
{
85
  GeglProperties    *o = GEGL_PROPERTIES (operation);
86 87
  gint           size, i, pos;
  GeglRectangle  dst_rect;
Hans Lo's avatar
Hans Lo committed
88

89

90
  if (o->direction == GEGL_SHIFT_DIRECTION_HORIZONTAL)
91
    {
92 93 94 95 96 97 98 99 100 101 102
      size = result->height;
      dst_rect.width  = result->width;
      dst_rect.height = 1;
      pos = result->y;
    }
  else
    {
      size = result->width;
      dst_rect.width  = 1;
      dst_rect.height = result->height;
      pos = result->x;
103
    }
Hans Lo's avatar
Hans Lo committed
104

105 106
  dst_rect.x = result->x;
  dst_rect.y = result->y;
Hans Lo's avatar
Hans Lo committed
107

108
  for (i = 0; i < size; i++)
Hans Lo's avatar
Hans Lo committed
109
    {
110 111 112 113
      GeglRectangle src_rect;
      gint shift = gegl_random_int_range (o->rand, i + pos, 0, 0, 0,
                                          -o->shift, o->shift + 1);

114
      if (o->direction == GEGL_SHIFT_DIRECTION_HORIZONTAL)
115
        {
116 117 118
          dst_rect.y = i + result->y;
          src_rect = dst_rect;
          src_rect.x = result->x + shift;
119
        }
120
      else
121
        {
122 123 124
          dst_rect.x = i + result->x;
          src_rect = dst_rect;
          src_rect.y = result->y + shift;
125 126
        }

127 128 129
      /* XXX: gegl_buffer_copy doesn't allow to set the abyss policy,
       * but we probably need _CLAMP here */
      gegl_buffer_copy (input, &src_rect, output, &dst_rect);
Hans Lo's avatar
Hans Lo committed
130
    }
131

Hans Lo's avatar
Hans Lo committed
132 133 134 135
  return  TRUE;
}

static void
136
gegl_op_class_init (GeglOpClass *klass)
Hans Lo's avatar
Hans Lo committed
137 138 139
{
  GeglOperationClass       *operation_class;
  GeglOperationFilterClass *filter_class;
140

Hans Lo's avatar
Hans Lo committed
141 142
  operation_class = GEGL_OPERATION_CLASS (klass);
  filter_class    = GEGL_OPERATION_FILTER_CLASS (klass);
143

Hans Lo's avatar
Hans Lo committed
144 145
  filter_class->process    = process;
  operation_class->prepare = prepare;
146

Hans Lo's avatar
Hans Lo committed
147
  gegl_operation_class_set_keys (operation_class,
148
    "name",        "gegl:shift",
149
    "title",       _("Shift"),
150
    "categories",  "distort",
151
    "license",     "GPL3+",
152
    "description", _("Shift each row or column of pixels by a random amount"),
Hans Lo's avatar
Hans Lo committed
153 154 155 156
    NULL);
}

#endif