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 2012 Ville Sokk <ville.sokk@gmail.com>
17  */
18 
19 #include "config.h"
20 #include <glib/gi18n-lib.h>
21 
22 #ifdef GEGL_PROPERTIES
23 
24 property_int (offset_x, _("Horizontal offset"), 0)
25     ui_range (0, 1024)
26     ui_meta  ("unit", "pixel-coordinate")
27     ui_meta  ("axis", "x")
28 
29 property_int (offset_y, _("Vertical offset"), 0)
30     ui_range (0, 1024)
31     ui_meta  ("unit", "pixel-coordinate")
32     ui_meta  ("axis", "y")
33 
34 #else
35 
36 #define GEGL_OP_FILTER
37 #define GEGL_OP_NAME     tile
38 #define GEGL_OP_C_SOURCE tile.c
39 
40 #include "gegl-op.h"
41 
42 static void
43 prepare (GeglOperation *operation)
44 {
45   const Babl *format;
46 
47   format = gegl_operation_get_source_format (operation, "input");
48 
49   gegl_operation_set_format (operation, "input", format);
50   gegl_operation_set_format (operation, "output", format);
51 }
52 
53 static GeglRectangle
54 get_bounding_box (GeglOperation *operation)
55 {
56   return gegl_rectangle_infinite_plane ();
57 }
58 
59 static GeglRectangle
60 get_required_for_output (GeglOperation       *operation,
61                          const gchar         *input_pad,
62                          const GeglRectangle *roi)
63 {
64   const GeglRectangle *in_rect =
65       gegl_operation_source_get_bounding_box (operation, input_pad);
66 
67   if (in_rect && ! gegl_rectangle_is_infinite_plane (in_rect))
68     {
69       return *in_rect;
70     }
71 
72   return *roi;
73 }
74 
75 static GeglRectangle
76 get_invalidated_by_change (GeglOperation       *operation,
77                            const gchar         *input_pad,
78                            const GeglRectangle *input_roi)
79 {
80   return gegl_rectangle_infinite_plane ();
81 }
82 
83 static gboolean
84 process (GeglOperation       *operation,
85          GeglBuffer          *input,
86          GeglBuffer          *output,
87          const GeglRectangle *result,
88          gint                 level)
89 {
90   GeglProperties *o = GEGL_PROPERTIES (operation);
91 
92   gegl_buffer_set_pattern (output, result, input,
93                            o->offset_x,
94                            o->offset_y);
95 
96   return TRUE;
97 }
98 
99 static gboolean
100 operation_process (GeglOperation        *operation,
101                    GeglOperationContext *context,
102                    const gchar          *output_prop,
103                    const GeglRectangle  *result,
104                    gint                  level)
105 {
106   GeglOperationClass  *operation_class;
107 
108   const GeglRectangle *in_rect =
109     gegl_operation_source_get_bounding_box (operation, "input");
110 
111   if (in_rect && gegl_rectangle_is_infinite_plane (in_rect))
112     {
113       gpointer in = gegl_operation_context_get_object (context, "input");
114       gegl_operation_context_take_object (context, "output",
115                                           g_object_ref (G_OBJECT (in)));
116       return TRUE;
117     }
118 
119   operation_class = GEGL_OPERATION_CLASS (gegl_op_parent_class);
120 
121   return operation_class->process (operation, context, output_prop, result,
122                                    gegl_operation_context_get_level (context));
123 }
124 
125 static void
126 gegl_op_class_init (GeglOpClass *klass)
127 {
128   GeglOperationClass       *operation_class;
129   GeglOperationFilterClass *filter_class;
130   gchar                    *composition = "<?xml version='1.0' encoding='UTF-8'?>"
131     "<gegl>"
132     "<node operation='gegl:crop'>"
133     "  <params>"
134     "    <param name='width'>200.0</param>"
135     "    <param name='height'>200.0</param>"
136     "  </params>"
137     "</node>"
138     "<node operation='gegl:tile'>"
139     "</node>"
140     "<node operation='gegl:load'>"
141     "  <params>"
142     "    <param name='path'>standard-aux.png</param>"
143     "  </params>"
144     "</node>"
145     "</gegl>";
146 
147   operation_class  = GEGL_OPERATION_CLASS (klass);
148   filter_class     = GEGL_OPERATION_FILTER_CLASS (klass);
149 
150   filter_class->process                      = process;
151   operation_class->process                   = operation_process;
152   operation_class->prepare                   = prepare;
153   operation_class->get_bounding_box          = get_bounding_box;
154   operation_class->get_required_for_output   = get_required_for_output;
155   operation_class->get_invalidated_by_change = get_invalidated_by_change;
156 
157   gegl_operation_class_set_keys (operation_class,
158       "name",                 "gegl:tile",
159       "title",                _("Tile"),
160       "categories",           "tile",
161       "position-dependent",   "true",
162       "reference-hash",       "166a4c955bb10d0a8472a2d8892baf39",
163       "reference-composition", composition,
164       "description",
165       _("Infinitely repeats the input image."),
166       NULL);
167 }
168 #endif
169