1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include <string.h>
21 
22 #include <cairo.h>
23 #include <gdk-pixbuf/gdk-pixbuf.h>
24 #include <gegl.h>
25 
26 #include "libgimpbase/gimpbase.h"
27 #include "libgimpmath/gimpmath.h"
28 
29 #include "core-types.h"
30 
31 #include "gegl/gimp-gegl-apply-operation.h"
32 #include "gegl/gimp-gegl-loops.h"
33 #include "gegl/gimp-gegl-mask-combine.h"
34 
35 #include "gimpchannel.h"
36 #include "gimpchannel-select.h"
37 #include "gimpchannel-combine.h"
38 #include "gimppickable.h"
39 #include "gimppickable-contiguous-region.h"
40 #include "gimpscanconvert.h"
41 
42 #include "vectors/gimpstroke.h"
43 #include "vectors/gimpvectors.h"
44 
45 #include "gimp-intl.h"
46 
47 
48 /*  basic selection functions  */
49 
50 void
gimp_channel_select_rectangle(GimpChannel * channel,gint x,gint y,gint w,gint h,GimpChannelOps op,gboolean feather,gdouble feather_radius_x,gdouble feather_radius_y,gboolean push_undo)51 gimp_channel_select_rectangle (GimpChannel    *channel,
52                                gint            x,
53                                gint            y,
54                                gint            w,
55                                gint            h,
56                                GimpChannelOps  op,
57                                gboolean        feather,
58                                gdouble         feather_radius_x,
59                                gdouble         feather_radius_y,
60                                gboolean        push_undo)
61 {
62   g_return_if_fail (GIMP_IS_CHANNEL (channel));
63   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
64 
65   if (push_undo)
66     gimp_channel_push_undo (channel, C_("undo-type", "Rectangle Select"));
67 
68   /*  if feathering for rect, make a new mask with the
69    *  rectangle and feather that with the old mask
70    */
71   if (feather)
72     {
73       GimpItem   *item = GIMP_ITEM (channel);
74       GeglBuffer *add_on;
75 
76       add_on = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
77                                                 gimp_item_get_width  (item),
78                                                 gimp_item_get_height (item)),
79                                 babl_format ("Y float"));
80 
81       gimp_gegl_mask_combine_rect (add_on, GIMP_CHANNEL_OP_REPLACE, x, y, w, h);
82 
83       gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL,
84                                feather_radius_x,
85                                feather_radius_y,
86                                TRUE);
87 
88       gimp_channel_combine_buffer (channel, add_on, op, 0, 0);
89       g_object_unref (add_on);
90     }
91   else
92     {
93       gimp_channel_combine_rect (channel, op, x, y, w, h);
94     }
95 }
96 
97 void
gimp_channel_select_ellipse(GimpChannel * channel,gint x,gint y,gint w,gint h,GimpChannelOps op,gboolean antialias,gboolean feather,gdouble feather_radius_x,gdouble feather_radius_y,gboolean push_undo)98 gimp_channel_select_ellipse (GimpChannel    *channel,
99                              gint            x,
100                              gint            y,
101                              gint            w,
102                              gint            h,
103                              GimpChannelOps  op,
104                              gboolean        antialias,
105                              gboolean        feather,
106                              gdouble         feather_radius_x,
107                              gdouble         feather_radius_y,
108                              gboolean        push_undo)
109 {
110   g_return_if_fail (GIMP_IS_CHANNEL (channel));
111   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
112 
113   if (push_undo)
114     gimp_channel_push_undo (channel, C_("undo-type", "Ellipse Select"));
115 
116   /*  if feathering for rect, make a new mask with the
117    *  rectangle and feather that with the old mask
118    */
119   if (feather)
120     {
121       GimpItem   *item = GIMP_ITEM (channel);
122       GeglBuffer *add_on;
123 
124       add_on = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
125                                                 gimp_item_get_width  (item),
126                                                 gimp_item_get_height (item)),
127                                 babl_format ("Y float"));
128 
129       gimp_gegl_mask_combine_ellipse (add_on, GIMP_CHANNEL_OP_REPLACE,
130                                       x, y, w, h, antialias);
131 
132       gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL,
133                                feather_radius_x,
134                                feather_radius_y,
135                                TRUE);
136 
137       gimp_channel_combine_buffer (channel, add_on, op, 0, 0);
138       g_object_unref (add_on);
139     }
140   else
141     {
142       gimp_channel_combine_ellipse (channel, op, x, y, w, h, antialias);
143     }
144 }
145 
146 void
gimp_channel_select_round_rect(GimpChannel * channel,gint x,gint y,gint w,gint h,gdouble corner_radius_x,gdouble corner_radius_y,GimpChannelOps op,gboolean antialias,gboolean feather,gdouble feather_radius_x,gdouble feather_radius_y,gboolean push_undo)147 gimp_channel_select_round_rect (GimpChannel         *channel,
148                                 gint                 x,
149                                 gint                 y,
150                                 gint                 w,
151                                 gint                 h,
152                                 gdouble              corner_radius_x,
153                                 gdouble              corner_radius_y,
154                                 GimpChannelOps       op,
155                                 gboolean             antialias,
156                                 gboolean             feather,
157                                 gdouble              feather_radius_x,
158                                 gdouble              feather_radius_y,
159                                 gboolean             push_undo)
160 {
161   g_return_if_fail (GIMP_IS_CHANNEL (channel));
162   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
163 
164   if (push_undo)
165     gimp_channel_push_undo (channel, C_("undo-type", "Rounded Rectangle Select"));
166 
167   /*  if feathering for rect, make a new mask with the
168    *  rectangle and feather that with the old mask
169    */
170   if (feather)
171     {
172       GimpItem   *item = GIMP_ITEM (channel);
173       GeglBuffer *add_on;
174 
175       add_on = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
176                                                 gimp_item_get_width  (item),
177                                                 gimp_item_get_height (item)),
178                                 babl_format ("Y float"));
179 
180       gimp_gegl_mask_combine_ellipse_rect (add_on, GIMP_CHANNEL_OP_REPLACE,
181                                            x, y, w, h,
182                                            corner_radius_x, corner_radius_y,
183                                            antialias);
184 
185       gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL,
186                                feather_radius_x,
187                                feather_radius_y,
188                                TRUE);
189 
190       gimp_channel_combine_buffer (channel, add_on, op, 0, 0);
191       g_object_unref (add_on);
192     }
193   else
194     {
195       gimp_channel_combine_ellipse_rect (channel, op, x, y, w, h,
196                                          corner_radius_x, corner_radius_y,
197                                          antialias);
198     }
199 }
200 
201 /*  select by GimpScanConvert functions  */
202 
203 void
gimp_channel_select_scan_convert(GimpChannel * channel,const gchar * undo_desc,GimpScanConvert * scan_convert,gint offset_x,gint offset_y,GimpChannelOps op,gboolean antialias,gboolean feather,gdouble feather_radius_x,gdouble feather_radius_y,gboolean push_undo)204 gimp_channel_select_scan_convert (GimpChannel     *channel,
205                                   const gchar     *undo_desc,
206                                   GimpScanConvert *scan_convert,
207                                   gint             offset_x,
208                                   gint             offset_y,
209                                   GimpChannelOps   op,
210                                   gboolean         antialias,
211                                   gboolean         feather,
212                                   gdouble          feather_radius_x,
213                                   gdouble          feather_radius_y,
214                                   gboolean         push_undo)
215 {
216   GimpItem   *item;
217   GeglBuffer *add_on;
218 
219   g_return_if_fail (GIMP_IS_CHANNEL (channel));
220   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
221   g_return_if_fail (undo_desc != NULL);
222   g_return_if_fail (scan_convert != NULL);
223 
224   if (push_undo)
225     gimp_channel_push_undo (channel, undo_desc);
226 
227   item = GIMP_ITEM (channel);
228 
229   add_on = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
230                                             gimp_item_get_width  (item),
231                                             gimp_item_get_height (item)),
232                             babl_format ("Y float"));
233 
234   gimp_scan_convert_render (scan_convert, add_on,
235                             offset_x, offset_y, antialias);
236 
237   if (feather)
238     gimp_gegl_apply_feather (add_on, NULL, NULL, add_on, NULL,
239                              feather_radius_x,
240                              feather_radius_y,
241                              TRUE);
242 
243   gimp_channel_combine_buffer (channel, add_on, op, 0, 0);
244   g_object_unref (add_on);
245 }
246 
247 void
gimp_channel_select_polygon(GimpChannel * channel,const gchar * undo_desc,gint n_points,const GimpVector2 * points,GimpChannelOps op,gboolean antialias,gboolean feather,gdouble feather_radius_x,gdouble feather_radius_y,gboolean push_undo)248 gimp_channel_select_polygon (GimpChannel       *channel,
249                              const gchar       *undo_desc,
250                              gint               n_points,
251                              const GimpVector2 *points,
252                              GimpChannelOps     op,
253                              gboolean           antialias,
254                              gboolean           feather,
255                              gdouble            feather_radius_x,
256                              gdouble            feather_radius_y,
257                              gboolean           push_undo)
258 {
259   GimpScanConvert *scan_convert;
260 
261   g_return_if_fail (GIMP_IS_CHANNEL (channel));
262   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
263   g_return_if_fail (undo_desc != NULL);
264 
265   scan_convert = gimp_scan_convert_new ();
266 
267   gimp_scan_convert_add_polyline (scan_convert, n_points, points, TRUE);
268 
269   gimp_channel_select_scan_convert (channel, undo_desc, scan_convert, 0, 0,
270                                     op, antialias, feather,
271                                     feather_radius_x, feather_radius_y,
272                                     push_undo);
273 
274   gimp_scan_convert_free (scan_convert);
275 }
276 
277 void
gimp_channel_select_vectors(GimpChannel * channel,const gchar * undo_desc,GimpVectors * vectors,GimpChannelOps op,gboolean antialias,gboolean feather,gdouble feather_radius_x,gdouble feather_radius_y,gboolean push_undo)278 gimp_channel_select_vectors (GimpChannel    *channel,
279                              const gchar    *undo_desc,
280                              GimpVectors    *vectors,
281                              GimpChannelOps  op,
282                              gboolean        antialias,
283                              gboolean        feather,
284                              gdouble         feather_radius_x,
285                              gdouble         feather_radius_y,
286                              gboolean        push_undo)
287 {
288   const GimpBezierDesc *bezier;
289 
290   g_return_if_fail (GIMP_IS_CHANNEL (channel));
291   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
292   g_return_if_fail (undo_desc != NULL);
293   g_return_if_fail (GIMP_IS_VECTORS (vectors));
294 
295   bezier = gimp_vectors_get_bezier (vectors);
296 
297   if (bezier && bezier->num_data > 4)
298     {
299       GimpScanConvert *scan_convert;
300 
301       scan_convert = gimp_scan_convert_new ();
302       gimp_scan_convert_add_bezier (scan_convert, bezier);
303 
304       gimp_channel_select_scan_convert (channel, undo_desc, scan_convert, 0, 0,
305                                         op, antialias, feather,
306                                         feather_radius_x, feather_radius_y,
307                                         push_undo);
308 
309       gimp_scan_convert_free (scan_convert);
310     }
311 }
312 
313 
314 /*  select by GimpChannel functions  */
315 
316 void
gimp_channel_select_buffer(GimpChannel * channel,const gchar * undo_desc,GeglBuffer * add_on,gint offset_x,gint offset_y,GimpChannelOps op,gboolean feather,gdouble feather_radius_x,gdouble feather_radius_y)317 gimp_channel_select_buffer (GimpChannel    *channel,
318                             const gchar    *undo_desc,
319                             GeglBuffer     *add_on,
320                             gint            offset_x,
321                             gint            offset_y,
322                             GimpChannelOps  op,
323                             gboolean        feather,
324                             gdouble         feather_radius_x,
325                             gdouble         feather_radius_y)
326 {
327   g_return_if_fail (GIMP_IS_CHANNEL (channel));
328   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
329   g_return_if_fail (undo_desc != NULL);
330   g_return_if_fail (GEGL_IS_BUFFER (add_on));
331 
332   gimp_channel_push_undo (channel, undo_desc);
333 
334   if (feather)
335     {
336       GimpItem   *item = GIMP_ITEM (channel);
337       GeglBuffer *add_on2;
338 
339       add_on2 = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
340                                                  gimp_item_get_width  (item),
341                                                  gimp_item_get_height (item)),
342                                  babl_format ("Y float"));
343 
344       gimp_gegl_mask_combine_buffer (add_on2, add_on,
345                                      GIMP_CHANNEL_OP_REPLACE,
346                                      offset_x, offset_y);
347 
348       gimp_gegl_apply_feather (add_on2, NULL, NULL, add_on2, NULL,
349                                feather_radius_x,
350                                feather_radius_y,
351                                TRUE);
352 
353       gimp_channel_combine_buffer (channel, add_on2, op, 0, 0);
354       g_object_unref (add_on2);
355     }
356   else
357     {
358       gimp_channel_combine_buffer (channel, add_on, op, offset_x, offset_y);
359     }
360 }
361 
362 void
gimp_channel_select_channel(GimpChannel * channel,const gchar * undo_desc,GimpChannel * add_on,gint offset_x,gint offset_y,GimpChannelOps op,gboolean feather,gdouble feather_radius_x,gdouble feather_radius_y)363 gimp_channel_select_channel (GimpChannel    *channel,
364                              const gchar    *undo_desc,
365                              GimpChannel    *add_on,
366                              gint            offset_x,
367                              gint            offset_y,
368                              GimpChannelOps  op,
369                              gboolean        feather,
370                              gdouble         feather_radius_x,
371                              gdouble         feather_radius_y)
372 {
373   g_return_if_fail (GIMP_IS_CHANNEL (channel));
374   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
375   g_return_if_fail (undo_desc != NULL);
376   g_return_if_fail (GIMP_IS_CHANNEL (add_on));
377 
378   gimp_channel_select_buffer (channel, undo_desc,
379                               gimp_drawable_get_buffer (GIMP_DRAWABLE (add_on)),
380                               offset_x, offset_y, op,
381                               feather,
382                               feather_radius_x, feather_radius_y);
383 }
384 
385 void
gimp_channel_select_alpha(GimpChannel * channel,GimpDrawable * drawable,GimpChannelOps op,gboolean feather,gdouble feather_radius_x,gdouble feather_radius_y)386 gimp_channel_select_alpha (GimpChannel    *channel,
387                            GimpDrawable   *drawable,
388                            GimpChannelOps  op,
389                            gboolean        feather,
390                            gdouble         feather_radius_x,
391                            gdouble         feather_radius_y)
392 {
393   GimpItem    *item;
394   GimpChannel *add_on;
395   gint         off_x, off_y;
396 
397   g_return_if_fail (GIMP_IS_CHANNEL (channel));
398   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
399   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
400 
401   item = GIMP_ITEM (channel);
402 
403   if (gimp_drawable_has_alpha (drawable))
404     {
405       add_on = gimp_channel_new_from_alpha (gimp_item_get_image (item),
406                                             drawable, NULL, NULL);
407     }
408   else
409     {
410       /*  no alpha is equivalent to completely opaque alpha,
411        *  so simply select the whole layer's extents.  --mitch
412        */
413       add_on = gimp_channel_new_mask (gimp_item_get_image (item),
414                                       gimp_item_get_width  (GIMP_ITEM (drawable)),
415                                       gimp_item_get_height (GIMP_ITEM (drawable)));
416       gimp_channel_all (add_on, FALSE);
417     }
418 
419   gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
420 
421   gimp_channel_select_channel (channel, C_("undo-type", "Alpha to Selection"), add_on,
422                                off_x, off_y,
423                                op, feather,
424                                feather_radius_x,
425                                feather_radius_y);
426   g_object_unref (add_on);
427 }
428 
429 void
gimp_channel_select_component(GimpChannel * channel,GimpChannelType component,GimpChannelOps op,gboolean feather,gdouble feather_radius_x,gdouble feather_radius_y)430 gimp_channel_select_component (GimpChannel     *channel,
431                                GimpChannelType  component,
432                                GimpChannelOps   op,
433                                gboolean         feather,
434                                gdouble          feather_radius_x,
435                                gdouble          feather_radius_y)
436 {
437   GimpItem    *item;
438   GimpChannel *add_on;
439   const gchar *desc;
440   gchar       *undo_desc;
441 
442   g_return_if_fail (GIMP_IS_CHANNEL (channel));
443   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
444 
445   item = GIMP_ITEM (channel);
446 
447   add_on = gimp_channel_new_from_component (gimp_item_get_image (item),
448                                             component, NULL, NULL);
449 
450   if (feather)
451     gimp_channel_feather (add_on,
452                           feather_radius_x,
453                           feather_radius_y,
454                           TRUE,
455                           FALSE /* no undo */);
456 
457   gimp_enum_get_value (GIMP_TYPE_CHANNEL_TYPE, component,
458                        NULL, NULL, &desc, NULL);
459 
460   undo_desc = g_strdup_printf (C_("undo-type", "%s Channel to Selection"), desc);
461 
462   gimp_channel_select_channel (channel, undo_desc, add_on,
463                                0, 0, op,
464                                FALSE, 0.0, 0.0);
465 
466   g_free (undo_desc);
467   g_object_unref (add_on);
468 }
469 
470 void
gimp_channel_select_fuzzy(GimpChannel * channel,GimpDrawable * drawable,gboolean sample_merged,gint x,gint y,gfloat threshold,gboolean select_transparent,GimpSelectCriterion select_criterion,gboolean diagonal_neighbors,GimpChannelOps op,gboolean antialias,gboolean feather,gdouble feather_radius_x,gdouble feather_radius_y)471 gimp_channel_select_fuzzy (GimpChannel         *channel,
472                            GimpDrawable        *drawable,
473                            gboolean             sample_merged,
474                            gint                 x,
475                            gint                 y,
476                            gfloat               threshold,
477                            gboolean             select_transparent,
478                            GimpSelectCriterion  select_criterion,
479                            gboolean             diagonal_neighbors,
480                            GimpChannelOps       op,
481                            gboolean             antialias,
482                            gboolean             feather,
483                            gdouble              feather_radius_x,
484                            gdouble              feather_radius_y)
485 {
486   GimpPickable *pickable;
487   GeglBuffer   *add_on;
488   gint          add_on_x = 0;
489   gint          add_on_y = 0;
490 
491   g_return_if_fail (GIMP_IS_CHANNEL (channel));
492   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
493   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
494 
495   if (sample_merged)
496     pickable = GIMP_PICKABLE (gimp_item_get_image (GIMP_ITEM (drawable)));
497   else
498     pickable = GIMP_PICKABLE (drawable);
499 
500   add_on = gimp_pickable_contiguous_region_by_seed (pickable,
501                                                     antialias,
502                                                     threshold,
503                                                     select_transparent,
504                                                     select_criterion,
505                                                     diagonal_neighbors,
506                                                     x, y);
507 
508   if (! sample_merged)
509     gimp_item_get_offset (GIMP_ITEM (drawable), &add_on_x, &add_on_y);
510 
511   gimp_channel_select_buffer (channel, C_("undo-type", "Fuzzy Select"),
512                               add_on, add_on_x, add_on_y,
513                               op,
514                               feather,
515                               feather_radius_x,
516                               feather_radius_y);
517   g_object_unref (add_on);
518 }
519 
520 void
gimp_channel_select_by_color(GimpChannel * channel,GimpDrawable * drawable,gboolean sample_merged,const GimpRGB * color,gfloat threshold,gboolean select_transparent,GimpSelectCriterion select_criterion,GimpChannelOps op,gboolean antialias,gboolean feather,gdouble feather_radius_x,gdouble feather_radius_y)521 gimp_channel_select_by_color (GimpChannel         *channel,
522                               GimpDrawable        *drawable,
523                               gboolean             sample_merged,
524                               const GimpRGB       *color,
525                               gfloat               threshold,
526                               gboolean             select_transparent,
527                               GimpSelectCriterion  select_criterion,
528                               GimpChannelOps       op,
529                               gboolean             antialias,
530                               gboolean             feather,
531                               gdouble              feather_radius_x,
532                               gdouble              feather_radius_y)
533 {
534   GimpPickable *pickable;
535   GeglBuffer   *add_on;
536   gint          add_on_x = 0;
537   gint          add_on_y = 0;
538 
539   g_return_if_fail (GIMP_IS_CHANNEL (channel));
540   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
541   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
542   g_return_if_fail (color != NULL);
543 
544   if (sample_merged)
545     pickable = GIMP_PICKABLE (gimp_item_get_image (GIMP_ITEM (drawable)));
546   else
547     pickable = GIMP_PICKABLE (drawable);
548 
549   add_on = gimp_pickable_contiguous_region_by_color (pickable,
550                                                      antialias,
551                                                      threshold,
552                                                      select_transparent,
553                                                      select_criterion,
554                                                      color);
555 
556   if (! sample_merged)
557     gimp_item_get_offset (GIMP_ITEM (drawable), &add_on_x, &add_on_y);
558 
559   gimp_channel_select_buffer (channel, C_("undo-type", "Select by Color"),
560                               add_on, add_on_x, add_on_y,
561                               op,
562                               feather,
563                               feather_radius_x,
564                               feather_radius_y);
565   g_object_unref (add_on);
566 }
567 
568 void
gimp_channel_select_by_index(GimpChannel * channel,GimpDrawable * drawable,gint index,GimpChannelOps op,gboolean feather,gdouble feather_radius_x,gdouble feather_radius_y)569 gimp_channel_select_by_index (GimpChannel    *channel,
570                               GimpDrawable   *drawable,
571                               gint            index,
572                               GimpChannelOps  op,
573                               gboolean        feather,
574                               gdouble         feather_radius_x,
575                               gdouble         feather_radius_y)
576 {
577   GeglBuffer *add_on;
578   gint        add_on_x = 0;
579   gint        add_on_y = 0;
580 
581   g_return_if_fail (GIMP_IS_CHANNEL (channel));
582   g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel)));
583   g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
584   g_return_if_fail (gimp_drawable_is_indexed (drawable));
585 
586   add_on = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
587                                             gimp_item_get_width  (GIMP_ITEM (drawable)),
588                                             gimp_item_get_height (GIMP_ITEM (drawable))),
589                             babl_format ("Y float"));
590 
591   gimp_gegl_index_to_mask (gimp_drawable_get_buffer (drawable), NULL,
592                            gimp_drawable_get_format_without_alpha (drawable),
593                            add_on, NULL,
594                            index);
595 
596   gimp_item_get_offset (GIMP_ITEM (drawable), &add_on_x, &add_on_y);
597 
598   gimp_channel_select_buffer (channel, C_("undo-type", "Select by Indexed Color"),
599                               add_on, add_on_x, add_on_y,
600                               op,
601                               feather,
602                               feather_radius_x,
603                               feather_radius_y);
604   g_object_unref (add_on);
605 }
606