168 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			168 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* PIKA - Photo and Image Kooker Application
 | 
						|
 * a rebranding of The GNU Image Manipulation Program (created with heckimp)
 | 
						|
 * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
 | 
						|
 *
 | 
						|
 * Original copyright, applying to most contents (license remains unchanged): 
 | 
						|
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 | 
						|
 *
 | 
						|
 * pikabycolorselecttool.c
 | 
						|
 *
 | 
						|
 * This program is free software: you can redistribute it and/or modify
 | 
						|
 * it under the terms of the GNU General Public License as published by
 | 
						|
 * the Free Software Foundation; either version 3 of the License, or
 | 
						|
 * (at your option) any later version.
 | 
						|
 *
 | 
						|
 * This program 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 General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License
 | 
						|
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
						|
 */
 | 
						|
 | 
						|
#include "config.h"
 | 
						|
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
#include <gegl.h>
 | 
						|
#include <gtk/gtk.h>
 | 
						|
 | 
						|
#include "libpikacolor/pikacolor.h"
 | 
						|
#include "libpikawidgets/pikawidgets.h"
 | 
						|
 | 
						|
#include "tools-types.h"
 | 
						|
 | 
						|
#include "core/pika.h"
 | 
						|
#include "core/pikacontainer.h"
 | 
						|
#include "core/pikaimage.h"
 | 
						|
#include "core/pikaimage-new.h"
 | 
						|
#include "core/pikaitem.h"
 | 
						|
#include "core/pikapickable.h"
 | 
						|
#include "core/pikapickable-contiguous-region.h"
 | 
						|
 | 
						|
#include "widgets/pikahelp-ids.h"
 | 
						|
 | 
						|
#include "display/pikadisplay.h"
 | 
						|
 | 
						|
#include "pikabycolorselecttool.h"
 | 
						|
#include "pikaregionselectoptions.h"
 | 
						|
#include "pikatoolcontrol.h"
 | 
						|
 | 
						|
#include "pika-intl.h"
 | 
						|
 | 
						|
 | 
						|
static GeglBuffer * pika_by_color_select_tool_get_mask (PikaRegionSelectTool *region_select,
 | 
						|
                                                        PikaDisplay          *display);
 | 
						|
 | 
						|
 | 
						|
G_DEFINE_TYPE (PikaByColorSelectTool, pika_by_color_select_tool,
 | 
						|
               PIKA_TYPE_REGION_SELECT_TOOL)
 | 
						|
 | 
						|
#define parent_class pika_by_color_select_tool_parent_class
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
pika_by_color_select_tool_register (PikaToolRegisterCallback  callback,
 | 
						|
                                    gpointer                  data)
 | 
						|
{
 | 
						|
  (* callback) (PIKA_TYPE_BY_COLOR_SELECT_TOOL,
 | 
						|
                PIKA_TYPE_REGION_SELECT_OPTIONS,
 | 
						|
                pika_region_select_options_gui,
 | 
						|
                0,
 | 
						|
                "pika-by-color-select-tool",
 | 
						|
                _("Select by Color"),
 | 
						|
                _("Select by Color Tool: Select regions with similar colors"),
 | 
						|
                N_("_By Color Select"), "<shift>O",
 | 
						|
                NULL, PIKA_HELP_TOOL_BY_COLOR_SELECT,
 | 
						|
                PIKA_ICON_TOOL_BY_COLOR_SELECT,
 | 
						|
                data);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
pika_by_color_select_tool_class_init (PikaByColorSelectToolClass *klass)
 | 
						|
{
 | 
						|
  PikaRegionSelectToolClass *region_class;
 | 
						|
 | 
						|
  region_class = PIKA_REGION_SELECT_TOOL_CLASS (klass);
 | 
						|
 | 
						|
  region_class->undo_desc = C_("command", "Select by Color");
 | 
						|
  region_class->get_mask  = pika_by_color_select_tool_get_mask;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
pika_by_color_select_tool_init (PikaByColorSelectTool *by_color_select)
 | 
						|
{
 | 
						|
  PikaTool *tool = PIKA_TOOL (by_color_select);
 | 
						|
 | 
						|
  pika_tool_control_set_tool_cursor (tool->control, PIKA_TOOL_CURSOR_HAND);
 | 
						|
}
 | 
						|
 | 
						|
static GeglBuffer *
 | 
						|
pika_by_color_select_tool_get_mask (PikaRegionSelectTool *region_select,
 | 
						|
                                    PikaDisplay          *display)
 | 
						|
{
 | 
						|
  PikaTool                *tool         = PIKA_TOOL (region_select);
 | 
						|
  PikaSelectionOptions    *sel_options  = PIKA_SELECTION_TOOL_GET_OPTIONS (tool);
 | 
						|
  PikaRegionSelectOptions *options      = PIKA_REGION_SELECT_TOOL_GET_OPTIONS (tool);
 | 
						|
  PikaImage               *image        = pika_display_get_image (display);
 | 
						|
  PikaImage               *select_image = NULL;
 | 
						|
  GList                   *drawables    = pika_image_get_selected_drawables (image);
 | 
						|
  PikaPickable            *pickable;
 | 
						|
  GeglBuffer              *mask         = NULL;
 | 
						|
  PikaRGB                  srgb;
 | 
						|
  gint                     x, y;
 | 
						|
 | 
						|
  x = region_select->x;
 | 
						|
  y = region_select->y;
 | 
						|
 | 
						|
  if (! options->sample_merged)
 | 
						|
    {
 | 
						|
      if (g_list_length (drawables) == 1)
 | 
						|
        {
 | 
						|
          gint off_x, off_y;
 | 
						|
 | 
						|
          pika_item_get_offset (drawables->data, &off_x, &off_y);
 | 
						|
 | 
						|
          x -= off_x;
 | 
						|
          y -= off_y;
 | 
						|
 | 
						|
          pickable = PIKA_PICKABLE (drawables->data);
 | 
						|
        }
 | 
						|
      else
 | 
						|
        {
 | 
						|
          select_image = pika_image_new_from_drawables (image->pika, drawables, FALSE, FALSE);
 | 
						|
          pika_container_remove (image->pika->images, PIKA_OBJECT (select_image));
 | 
						|
 | 
						|
          pickable = PIKA_PICKABLE (select_image);
 | 
						|
          pika_pickable_flush (pickable);
 | 
						|
        }
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      pickable = PIKA_PICKABLE (image);
 | 
						|
    }
 | 
						|
 | 
						|
  g_list_free (drawables);
 | 
						|
  pika_pickable_flush (pickable);
 | 
						|
 | 
						|
  if (pika_pickable_get_color_at (pickable, x, y, &srgb))
 | 
						|
    {
 | 
						|
      PikaRGB color;
 | 
						|
 | 
						|
      pika_pickable_srgb_to_image_color (pickable, &srgb, &color);
 | 
						|
 | 
						|
      mask = pika_pickable_contiguous_region_by_color (pickable,
 | 
						|
                                                       sel_options->antialias,
 | 
						|
                                                       options->threshold / 255.0,
 | 
						|
                                                       options->select_transparent,
 | 
						|
                                                       options->select_criterion,
 | 
						|
                                                       &color);
 | 
						|
    }
 | 
						|
 | 
						|
  if (select_image)
 | 
						|
    g_object_unref (select_image);
 | 
						|
 | 
						|
  return mask;
 | 
						|
}
 |