1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimpoperationhistogramsink.c
5  * Copyright (C) 2012 Øyvind Kolås
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include <gegl.h>
24 
25 #include "operations-types.h"
26 
27 #include "core/gimphistogram.h"
28 
29 #include "gimpoperationhistogramsink.h"
30 
31 
32 enum
33 {
34   PROP_0,
35   PROP_AUX,
36   PROP_HISTOGRAM
37 };
38 
39 
40 static void     gimp_operation_histogram_sink_finalize     (GObject             *object);
41 static void     gimp_operation_histogram_sink_get_property (GObject             *object,
42                                                             guint                prop_id,
43                                                             GValue              *value,
44                                                             GParamSpec          *pspec);
45 static void     gimp_operation_histogram_sink_set_property (GObject             *object,
46                                                             guint                prop_id,
47                                                             const GValue        *value,
48                                                             GParamSpec          *pspec);
49 
50 static void     gimp_operation_histogram_sink_attach       (GeglOperation       *operation);
51 static void     gimp_operation_histogram_sink_prepare      (GeglOperation       *operation);
52 static GeglRectangle
53      gimp_operation_histogram_sink_get_required_for_output (GeglOperation        *self,
54                                                             const gchar         *input_pad,
55                                                             const GeglRectangle *roi);
56 static gboolean gimp_operation_histogram_sink_process      (GeglOperation       *operation,
57                                                             GeglOperationContext     *context,
58                                                             const gchar         *output_prop,
59                                                             const GeglRectangle *result,
60                                                             gint                 level);
61 
62 
G_DEFINE_TYPE(GimpOperationHistogramSink,gimp_operation_histogram_sink,GEGL_TYPE_OPERATION_SINK)63 G_DEFINE_TYPE (GimpOperationHistogramSink, gimp_operation_histogram_sink,
64                GEGL_TYPE_OPERATION_SINK)
65 
66 #define parent_class gimp_operation_histogram_sink_parent_class
67 
68 
69 static void
70 gimp_operation_histogram_sink_class_init (GimpOperationHistogramSinkClass *klass)
71 {
72   GObjectClass       *object_class    = G_OBJECT_CLASS (klass);
73   GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass);
74 
75   object_class->finalize     = gimp_operation_histogram_sink_finalize;
76   object_class->set_property = gimp_operation_histogram_sink_set_property;
77   object_class->get_property = gimp_operation_histogram_sink_get_property;
78 
79   gegl_operation_class_set_keys (operation_class,
80                                  "name"       , "gimp:histogram-sink",
81                                  "categories" , "color",
82                                  "description", "GIMP Histogram sink operation",
83                                  NULL);
84 
85   operation_class->attach                  = gimp_operation_histogram_sink_attach;
86   operation_class->prepare                 = gimp_operation_histogram_sink_prepare;
87   operation_class->get_required_for_output = gimp_operation_histogram_sink_get_required_for_output;
88   operation_class->process                 = gimp_operation_histogram_sink_process;
89 
90   g_object_class_install_property (object_class, PROP_AUX,
91                                    g_param_spec_object ("aux",
92                                                         "Aux",
93                                                         "Auxiliary image buffer input pad.",
94                                                         GEGL_TYPE_BUFFER,
95                                                         G_PARAM_READWRITE |
96                                                         GEGL_PARAM_PAD_INPUT));
97 
98   g_object_class_install_property (object_class, PROP_HISTOGRAM,
99                                    g_param_spec_object ("histogram",
100                                                         "Histogram",
101                                                         "The result histogram",
102                                                         GIMP_TYPE_HISTOGRAM,
103                                                         G_PARAM_READWRITE));
104 }
105 
106 static void
gimp_operation_histogram_sink_init(GimpOperationHistogramSink * self)107 gimp_operation_histogram_sink_init (GimpOperationHistogramSink *self)
108 {
109 }
110 
111 static void
gimp_operation_histogram_sink_finalize(GObject * object)112 gimp_operation_histogram_sink_finalize (GObject *object)
113 {
114   GimpOperationHistogramSink *sink = GIMP_OPERATION_HISTOGRAM_SINK (object);
115 
116   g_clear_object (&sink->histogram);
117 
118   G_OBJECT_CLASS (parent_class)->finalize (object);
119 }
120 
121 static void
gimp_operation_histogram_sink_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)122 gimp_operation_histogram_sink_get_property (GObject    *object,
123                                             guint       prop_id,
124                                             GValue     *value,
125                                             GParamSpec *pspec)
126 {
127   GimpOperationHistogramSink *sink = GIMP_OPERATION_HISTOGRAM_SINK (object);
128 
129   switch (prop_id)
130     {
131     case PROP_AUX:
132       break;
133 
134     case PROP_HISTOGRAM:
135       g_value_set_pointer (value, sink->histogram);
136       break;
137 
138     default:
139       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
140       break;
141     }
142 }
143 
144 static void
gimp_operation_histogram_sink_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)145 gimp_operation_histogram_sink_set_property (GObject      *object,
146                                             guint         prop_id,
147                                             const GValue *value,
148                                             GParamSpec   *pspec)
149 {
150   GimpOperationHistogramSink *sink = GIMP_OPERATION_HISTOGRAM_SINK (object);
151 
152   switch (prop_id)
153     {
154     case PROP_AUX:
155       break;
156 
157     case PROP_HISTOGRAM:
158       if (sink->histogram)
159         g_object_unref (sink->histogram);
160       sink->histogram = g_value_dup_object (value);
161       break;
162 
163     default:
164       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
165       break;
166     }
167 }
168 
169 static void
gimp_operation_histogram_sink_attach(GeglOperation * self)170 gimp_operation_histogram_sink_attach (GeglOperation *self)
171 {
172   GeglOperation *operation    = GEGL_OPERATION (self);
173   GObjectClass  *object_class = G_OBJECT_GET_CLASS (self);
174 
175   GEGL_OPERATION_CLASS (parent_class)->attach (self);
176 
177   gegl_operation_create_pad (operation,
178                              g_object_class_find_property (object_class,
179                                                            "aux"));
180 }
181 
182 static void
gimp_operation_histogram_sink_prepare(GeglOperation * operation)183 gimp_operation_histogram_sink_prepare (GeglOperation *operation)
184 {
185   /* XXX gegl_operation_set_format (operation, "input", babl_format ("Y u8")); */
186   gegl_operation_set_format (operation, "aux",   babl_format ("Y float"));
187 }
188 
189 static GeglRectangle
gimp_operation_histogram_sink_get_required_for_output(GeglOperation * self,const gchar * input_pad,const GeglRectangle * roi)190 gimp_operation_histogram_sink_get_required_for_output (GeglOperation       *self,
191                                                        const gchar         *input_pad,
192                                                        const GeglRectangle *roi)
193 {
194   /* dunno what to do here, make a wild guess */
195   return *roi;
196 }
197 
198 static gboolean
gimp_operation_histogram_sink_process(GeglOperation * operation,GeglOperationContext * context,const gchar * output_prop,const GeglRectangle * result,gint level)199 gimp_operation_histogram_sink_process (GeglOperation        *operation,
200                                        GeglOperationContext *context,
201                                        const gchar          *output_prop,
202                                        const GeglRectangle  *result,
203                                        gint                  level)
204 {
205   GeglBuffer *input;
206   GeglBuffer *aux;
207 
208   if (strcmp (output_prop, "output"))
209     {
210       g_warning ("requested processing of %s pad on a sink", output_prop);
211       return FALSE;
212     }
213 
214   input = (GeglBuffer*) gegl_operation_context_dup_object (context, "input");
215   aux   = (GeglBuffer*) gegl_operation_context_dup_object (context, "aux");
216 
217   if (! input)
218     {
219       g_warning ("received NULL input");
220 
221       return FALSE;
222     }
223 
224   if (aux)
225     {
226       /* do hist with mask */
227 
228       g_printerr ("aux format: %s\n",
229                   babl_get_name (gegl_buffer_get_format (aux)));
230 
231       g_object_unref (aux);
232     }
233   else
234     {
235       /* without */
236     }
237 
238   g_printerr ("input format: %s\n",
239               babl_get_name (gegl_buffer_get_format (input)));
240 
241   g_object_unref (input);
242 
243   return TRUE;
244 }
245