From a7b84ded8e14eaf504edf702320096a1a47dd678 Mon Sep 17 00:00:00 2001 From: Thomas Manni Date: Wed, 20 May 2015 15:19:30 +0200 Subject: [PATCH] Bug 325564 - Use CIE LCH instead of HSL for layer mode Color Add Hue, Chroma, Color and Lightness layer modes in LCH color space. --- app/actions/context-commands.c | 6 +- app/actions/layers-commands.c | 6 +- app/core/core-enums.c | 16 +- app/core/core-enums.h | 12 +- app/gegl/gimp-gegl-nodes.c | 4 + app/operations/Makefile.am | 8 + app/operations/gimp-operations.c | 8 + app/operations/gimplayermodefunctions.c | 21 +- app/operations/gimplayermodefunctions.h | 3 +- app/operations/gimpoperationlchchromamode.c | 204 ++++++++++++++++++ app/operations/gimpoperationlchchromamode.h | 72 +++++++ app/operations/gimpoperationlchcolormode.c | 193 +++++++++++++++++ app/operations/gimpoperationlchcolormode.h | 72 +++++++ app/operations/gimpoperationlchhuemode.c | 204 ++++++++++++++++++ app/operations/gimpoperationlchhuemode.h | 72 +++++++ .../gimpoperationlchlightnessmode.c | 187 ++++++++++++++++ .../gimpoperationlchlightnessmode.h | 72 +++++++ app/paint/gimppaintcore-loops.c | 2 +- app/widgets/gimpwidgets-constructors.c | 12 +- devel-docs/libgimp/tmpl/gimpenums.sgml | 4 + libgimp/gimpenums.h | 6 +- tools/pdbgen/enums.pl | 10 +- 22 files changed, 1176 insertions(+), 18 deletions(-) create mode 100644 app/operations/gimpoperationlchchromamode.c create mode 100644 app/operations/gimpoperationlchchromamode.h create mode 100644 app/operations/gimpoperationlchcolormode.c create mode 100644 app/operations/gimpoperationlchcolormode.h create mode 100644 app/operations/gimpoperationlchhuemode.c create mode 100644 app/operations/gimpoperationlchhuemode.h create mode 100644 app/operations/gimpoperationlchlightnessmode.c create mode 100644 app/operations/gimpoperationlchlightnessmode.h diff --git a/app/actions/context-commands.c b/app/actions/context-commands.c index 321bada99b..449557c8bd 100644 --- a/app/actions/context-commands.c +++ b/app/actions/context-commands.c @@ -72,7 +72,11 @@ static const GimpLayerModeEffects paint_modes[] = GIMP_HUE_MODE, GIMP_SATURATION_MODE, GIMP_COLOR_MODE, - GIMP_VALUE_MODE + GIMP_VALUE_MODE, + GIMP_LCH_HUE_MODE, + GIMP_LCH_CHROMA_MODE, + GIMP_LCH_COLOR_MODE, + GIMP_LCH_LIGHTNESS_MODE }; diff --git a/app/actions/layers-commands.c b/app/actions/layers-commands.c index bd0e7829d1..409024e4ba 100644 --- a/app/actions/layers-commands.c +++ b/app/actions/layers-commands.c @@ -97,7 +97,11 @@ static const GimpLayerModeEffects layer_modes[] = GIMP_HUE_MODE, GIMP_SATURATION_MODE, GIMP_COLOR_MODE, - GIMP_VALUE_MODE + GIMP_VALUE_MODE, + GIMP_LCH_HUE_MODE, + GIMP_LCH_CHROMA_MODE, + GIMP_LCH_COLOR_MODE, + GIMP_LCH_LIGHTNESS_MODE }; diff --git a/app/core/core-enums.c b/app/core/core-enums.c index cfad22ed1b..a439bc7173 100644 --- a/app/core/core-enums.c +++ b/app/core/core-enums.c @@ -276,6 +276,10 @@ gimp_layer_mode_effects_get_type (void) { GIMP_GRAIN_MERGE_MODE, "GIMP_GRAIN_MERGE_MODE", "grain-merge-mode" }, { GIMP_COLOR_ERASE_MODE, "GIMP_COLOR_ERASE_MODE", "color-erase-mode" }, { GIMP_NEW_OVERLAY_MODE, "GIMP_NEW_OVERLAY_MODE", "new-overlay-mode" }, + { GIMP_LCH_HUE_MODE, "GIMP_LCH_HUE_MODE", "lch-hue-mode" }, + { GIMP_LCH_CHROMA_MODE, "GIMP_LCH_CHROMA_MODE", "lch-chroma-mode" }, + { GIMP_LCH_COLOR_MODE, "GIMP_LCH_COLOR_MODE", "lch-color-mode" }, + { GIMP_LCH_LIGHTNESS_MODE, "GIMP_LCH_LIGHTNESS_MODE", "lch-lightness-mode" }, { GIMP_ERASE_MODE, "GIMP_ERASE_MODE", "erase-mode" }, { GIMP_REPLACE_MODE, "GIMP_REPLACE_MODE", "replace-mode" }, { GIMP_ANTI_ERASE_MODE, "GIMP_ANTI_ERASE_MODE", "anti-erase-mode" }, @@ -295,10 +299,10 @@ gimp_layer_mode_effects_get_type (void) { GIMP_SUBTRACT_MODE, NC_("layer-mode-effects", "Subtract"), NULL }, { GIMP_DARKEN_ONLY_MODE, NC_("layer-mode-effects", "Darken only"), NULL }, { GIMP_LIGHTEN_ONLY_MODE, NC_("layer-mode-effects", "Lighten only"), NULL }, - { GIMP_HUE_MODE, NC_("layer-mode-effects", "Hue"), NULL }, - { GIMP_SATURATION_MODE, NC_("layer-mode-effects", "Saturation"), NULL }, - { GIMP_COLOR_MODE, NC_("layer-mode-effects", "Color"), NULL }, - { GIMP_VALUE_MODE, NC_("layer-mode-effects", "Value"), NULL }, + { GIMP_HUE_MODE, NC_("layer-mode-effects", "Hue (HSV)"), NULL }, + { GIMP_SATURATION_MODE, NC_("layer-mode-effects", "Saturation (HSV)"), NULL }, + { GIMP_COLOR_MODE, NC_("layer-mode-effects", "Color (HSV)"), NULL }, + { GIMP_VALUE_MODE, NC_("layer-mode-effects", "Value (HSV)"), NULL }, { GIMP_DIVIDE_MODE, NC_("layer-mode-effects", "Divide"), NULL }, { GIMP_DODGE_MODE, NC_("layer-mode-effects", "Dodge"), NULL }, { GIMP_BURN_MODE, NC_("layer-mode-effects", "Burn"), NULL }, @@ -308,6 +312,10 @@ gimp_layer_mode_effects_get_type (void) { GIMP_GRAIN_MERGE_MODE, NC_("layer-mode-effects", "Grain merge"), NULL }, { GIMP_COLOR_ERASE_MODE, NC_("layer-mode-effects", "Color erase"), NULL }, { GIMP_NEW_OVERLAY_MODE, NC_("layer-mode-effects", "Overlay"), NULL }, + { GIMP_LCH_HUE_MODE, NC_("layer-mode-effects", "Hue (LCH)"), NULL }, + { GIMP_LCH_CHROMA_MODE, NC_("layer-mode-effects", "Chroma (LCH)"), NULL }, + { GIMP_LCH_COLOR_MODE, NC_("layer-mode-effects", "Color (LCH)"), NULL }, + { GIMP_LCH_LIGHTNESS_MODE, NC_("layer-mode-effects", "Lightness (LCH)"), NULL }, { GIMP_ERASE_MODE, NC_("layer-mode-effects", "Erase"), NULL }, { GIMP_REPLACE_MODE, NC_("layer-mode-effects", "Replace"), NULL }, { GIMP_ANTI_ERASE_MODE, NC_("layer-mode-effects", "Anti erase"), NULL }, diff --git a/app/core/core-enums.h b/app/core/core-enums.h index 4ec137b278..374c8102c8 100644 --- a/app/core/core-enums.h +++ b/app/core/core-enums.h @@ -150,10 +150,10 @@ typedef enum GIMP_SUBTRACT_MODE, /*< desc="Subtract" >*/ GIMP_DARKEN_ONLY_MODE, /*< desc="Darken only" >*/ GIMP_LIGHTEN_ONLY_MODE, /*< desc="Lighten only" >*/ - GIMP_HUE_MODE, /*< desc="Hue" >*/ - GIMP_SATURATION_MODE, /*< desc="Saturation" >*/ - GIMP_COLOR_MODE, /*< desc="Color" >*/ - GIMP_VALUE_MODE, /*< desc="Value" >*/ + GIMP_HUE_MODE, /*< desc="Hue (HSV)" >*/ + GIMP_SATURATION_MODE, /*< desc="Saturation (HSV)" >*/ + GIMP_COLOR_MODE, /*< desc="Color (HSV)" >*/ + GIMP_VALUE_MODE, /*< desc="Value (HSV)" >*/ GIMP_DIVIDE_MODE, /*< desc="Divide" >*/ GIMP_DODGE_MODE, /*< desc="Dodge" >*/ GIMP_BURN_MODE, /*< desc="Burn" >*/ @@ -163,6 +163,10 @@ typedef enum GIMP_GRAIN_MERGE_MODE, /*< desc="Grain merge" >*/ GIMP_COLOR_ERASE_MODE, /*< desc="Color erase" >*/ GIMP_NEW_OVERLAY_MODE, /*< desc="Overlay" >*/ + GIMP_LCH_HUE_MODE, /*< desc="Hue (LCH)" >*/ + GIMP_LCH_CHROMA_MODE, /*< desc="Chroma (LCH)" >*/ + GIMP_LCH_COLOR_MODE, /*< desc="Color (LCH)" >*/ + GIMP_LCH_LIGHTNESS_MODE, /*< desc="Lightness (LCH)" >*/ /* internal modes, not available to the PDB */ GIMP_ERASE_MODE = 1000, /*< pdb-skip, desc="Erase" >*/ diff --git a/app/gegl/gimp-gegl-nodes.c b/app/gegl/gimp-gegl-nodes.c index 7db279cb58..1a27c15d15 100644 --- a/app/gegl/gimp-gegl-nodes.c +++ b/app/gegl/gimp-gegl-nodes.c @@ -177,6 +177,10 @@ gimp_gegl_mode_node_set_mode (GeglNode *node, case GIMP_ERASE_MODE: operation = "gimp:erase-mode"; break; case GIMP_REPLACE_MODE: operation = "gimp:replace-mode"; break; case GIMP_ANTI_ERASE_MODE: operation = "gimp:anti-erase-mode"; break; + case GIMP_LCH_HUE_MODE: operation = "gimp:lch-hue-mode"; break; + case GIMP_LCH_CHROMA_MODE: operation = "gimp:lch-chroma-mode"; break; + case GIMP_LCH_COLOR_MODE: operation = "gimp:lch-color-mode"; break; + case GIMP_LCH_LIGHTNESS_MODE: operation = "gimp:lch-lightness-mode"; break; default: break; } diff --git a/app/operations/Makefile.am b/app/operations/Makefile.am index e65b1c77fe..79cd653178 100644 --- a/app/operations/Makefile.am +++ b/app/operations/Makefile.am @@ -142,6 +142,14 @@ libappoperations_generic_a_sources = \ gimpoperationgrainmergemode.h \ gimpoperationcolorerasemode.c \ gimpoperationcolorerasemode.h \ + gimpoperationlchhuemode.c \ + gimpoperationlchhuemode.h \ + gimpoperationlchchromamode.c \ + gimpoperationlchchromamode.h \ + gimpoperationlchcolormode.c \ + gimpoperationlchcolormode.h \ + gimpoperationlchlightnessmode.c \ + gimpoperationlchlightnessmode.h \ gimpoperationerasemode.c \ gimpoperationerasemode.h \ gimpoperationreplacemode.c \ diff --git a/app/operations/gimp-operations.c b/app/operations/gimp-operations.c index 35db242889..a1a7e89008 100644 --- a/app/operations/gimp-operations.c +++ b/app/operations/gimp-operations.c @@ -77,6 +77,10 @@ #include "gimpoperationgrainextractmode.h" #include "gimpoperationgrainmergemode.h" #include "gimpoperationcolorerasemode.h" +#include "gimpoperationlchhuemode.h" +#include "gimpoperationlchchromamode.h" +#include "gimpoperationlchcolormode.h" +#include "gimpoperationlchlightnessmode.h" #include "gimpoperationerasemode.h" #include "gimpoperationreplacemode.h" #include "gimpoperationantierasemode.h" @@ -134,6 +138,10 @@ gimp_operations_init (void) g_type_class_ref (GIMP_TYPE_OPERATION_GRAIN_EXTRACT_MODE); g_type_class_ref (GIMP_TYPE_OPERATION_GRAIN_MERGE_MODE); g_type_class_ref (GIMP_TYPE_OPERATION_COLOR_ERASE_MODE); + g_type_class_ref (GIMP_TYPE_OPERATION_LCH_HUE_MODE); + g_type_class_ref (GIMP_TYPE_OPERATION_LCH_CHROMA_MODE); + g_type_class_ref (GIMP_TYPE_OPERATION_LCH_COLOR_MODE); + g_type_class_ref (GIMP_TYPE_OPERATION_LCH_LIGHTNESS_MODE); g_type_class_ref (GIMP_TYPE_OPERATION_ERASE_MODE); g_type_class_ref (GIMP_TYPE_OPERATION_REPLACE_MODE); g_type_class_ref (GIMP_TYPE_OPERATION_ANTI_ERASE_MODE); diff --git a/app/operations/gimplayermodefunctions.c b/app/operations/gimplayermodefunctions.c index b1bdad0f28..31cf54a457 100644 --- a/app/operations/gimplayermodefunctions.c +++ b/app/operations/gimplayermodefunctions.c @@ -49,12 +49,18 @@ #include "gimpoperationgrainextractmode.h" #include "gimpoperationgrainmergemode.h" #include "gimpoperationcolorerasemode.h" +#include "gimpoperationlchhuemode.h" +#include "gimpoperationlchchromamode.h" +#include "gimpoperationlchcolormode.h" +#include "gimpoperationlchlightnessmode.h" #include "gimpoperationerasemode.h" #include "gimpoperationreplacemode.h" #include "gimpoperationantierasemode.h" + GimpLayerModeFunction -get_layer_mode_function (GimpLayerModeEffects paint_mode) +get_layer_mode_function (GimpLayerModeEffects paint_mode, + gboolean linear_mode) { GimpLayerModeFunction func = gimp_operation_normal_mode_process_pixels; @@ -84,9 +90,22 @@ get_layer_mode_function (GimpLayerModeEffects paint_mode) case GIMP_GRAIN_MERGE_MODE: func = gimp_operation_grain_merge_mode_process_pixels; break; case GIMP_COLOR_ERASE_MODE: func = gimp_operation_color_erase_mode_process_pixels; break; case GIMP_NEW_OVERLAY_MODE: func = gimp_operation_overlay_mode_process_pixels; break; + case GIMP_LCH_HUE_MODE: func = linear_mode ? + gimp_operation_lch_hue_mode_process_pixels_linear : + gimp_operation_lch_hue_mode_process_pixels; break; + case GIMP_LCH_CHROMA_MODE: func = linear_mode ? + gimp_operation_lch_chroma_mode_process_pixels_linear : + gimp_operation_lch_chroma_mode_process_pixels; break; + case GIMP_LCH_COLOR_MODE: func = linear_mode ? + gimp_operation_lch_color_mode_process_pixels_linear : + gimp_operation_lch_color_mode_process_pixels; break; + case GIMP_LCH_LIGHTNESS_MODE: func = linear_mode ? + gimp_operation_lch_lightness_mode_process_pixels_linear : + gimp_operation_lch_lightness_mode_process_pixels; break; case GIMP_ERASE_MODE: func = gimp_operation_erase_mode_process_pixels; break; case GIMP_REPLACE_MODE: func = gimp_operation_replace_mode_process_pixels; break; case GIMP_ANTI_ERASE_MODE: func = gimp_operation_anti_erase_mode_process_pixels; break; + default: g_warning ("No direct function for layer mode (%d), using gimp:normal-mode", paint_mode); func = gimp_operation_normal_mode_process_pixels; diff --git a/app/operations/gimplayermodefunctions.h b/app/operations/gimplayermodefunctions.h index f92a61f394..8830fd548e 100644 --- a/app/operations/gimplayermodefunctions.h +++ b/app/operations/gimplayermodefunctions.h @@ -21,6 +21,7 @@ #ifndef __GIMP_LAYER_MODE_FUNCTIONS_H__ #define __GIMP_LAYER_MODE_FUNCTIONS_H__ -GimpLayerModeFunction get_layer_mode_function (GimpLayerModeEffects paint_mode); +GimpLayerModeFunction get_layer_mode_function (GimpLayerModeEffects paint_mode, + gboolean linear_mode); #endif /* __GIMP_LAYER_MODE_FUNCTIONS_H__ */ diff --git a/app/operations/gimpoperationlchchromamode.c b/app/operations/gimpoperationlchchromamode.c new file mode 100644 index 0000000000..b4dd037cdd --- /dev/null +++ b/app/operations/gimpoperationlchchromamode.c @@ -0,0 +1,204 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpoperationlchchromamode.c + * Copyright (C) 2015 Elle Stone + * Massimo Valentini + * Thomas Manni + * + * 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 . + */ + +#include "config.h" + +#include +#include +#include + +#include "libgimpmath/gimpmath.h" + +#include "operations-types.h" + +#include "gimpoperationlchchromamode.h" + + +static gboolean gimp_operation_lch_chroma_mode_process (GeglOperation *operation, + void *in_buf, + void *aux_buf, + void *aux2_buf, + void *out_buf, + glong samples, + const GeglRectangle *roi, + gint level); + + +G_DEFINE_TYPE (GimpOperationLchChromaMode, gimp_operation_lch_chroma_mode, + GIMP_TYPE_OPERATION_POINT_LAYER_MODE) + +#define parent_class gimp_operation_lch_chroma_mode_parent_class + + +static void +gimp_operation_lch_chroma_mode_class_init (GimpOperationLchChromaModeClass *klass) +{ + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; + + operation_class = GEGL_OPERATION_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); + + operation_class->want_in_place = FALSE; + + gegl_operation_class_set_keys (operation_class, + "name", "gimp:lch-chroma-mode", + "description", "GIMP LCH chroma mode operation", + NULL); + + point_class->process = gimp_operation_lch_chroma_mode_process; +} + +static void +gimp_operation_lch_chroma_mode_init (GimpOperationLchChromaMode *self) +{ +} + +static gboolean +gimp_operation_lch_chroma_mode_process (GeglOperation *operation, + void *in_buf, + void *aux_buf, + void *aux2_buf, + void *out_buf, + glong samples, + const GeglRectangle *roi, + gint level) +{ + GimpOperationPointLayerMode *gimp_op = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = gimp_op->opacity; + gboolean linear = gimp_op->linear; + + return (linear ? gimp_operation_lch_chroma_mode_process_pixels_linear : + gimp_operation_lch_chroma_mode_process_pixels) + (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, level); +} + +static void +chroma_pre_process (const Babl *format, + const gfloat *in, + const gfloat *layer, + gfloat *out, + glong samples) +{ + gfloat tmp[4 * samples], *layer_lab = tmp; + gint i; + + babl_process (babl_fish (format, "CIE Lab alpha float"), in, out, samples); + babl_process (babl_fish (format, "CIE Lab alpha float"), layer, layer_lab, samples); + + for (i = 0; i < samples; ++i) + { + gfloat A1 = out[4 * i + 1]; + gfloat B1 = out[4 * i + 2]; + gfloat c1 = hypot (A1, B1); + + if (c1 != 0) + { + gfloat A2 = layer_lab[4 * i + 1]; + gfloat B2 = layer_lab[4 * i + 2]; + gfloat c2 = hypot (A2, B2); + gfloat A = c2 * A1 / c1; + gfloat B = c2 * B1 / c1; + + out[4 * i + 1] = A; + out[4 * i + 2] = B; + } + } + + babl_process (babl_fish ("CIE Lab alpha float", format), out, out, samples); +} + +static void +chroma_post_process (const gfloat *in, + const gfloat *layer, + const gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples) +{ + while (samples--) + { + gfloat comp_alpha, new_alpha; + + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= *mask++; + + new_alpha = in[ALPHA] + (1.0f - in[ALPHA]) * comp_alpha; + + if (comp_alpha && new_alpha) + { + gfloat ratio = comp_alpha / new_alpha; + + out[RED] = out[RED] * ratio + in[RED] * (1.0f - ratio); + out[GREEN] = out[GREEN] * ratio + in[GREEN] * (1.0f - ratio); + out[BLUE] = out[BLUE] * ratio + in[BLUE] * (1.0f - ratio); + } + else + { + gint b; + + for (b = RED; b < ALPHA; b++) + { + out[b] = in[b]; + } + } + + out[ALPHA] = in[ALPHA]; + + in += 4; + layer += 4; + out += 4; + } +} + +gboolean +gimp_operation_lch_chroma_mode_process_pixels_linear (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level) +{ + chroma_pre_process (babl_format ("RGBA float"), in, layer, out, samples); + chroma_post_process (in, layer, mask, out, opacity, samples); + + return TRUE; +} + +gboolean +gimp_operation_lch_chroma_mode_process_pixels (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level) +{ + chroma_pre_process (babl_format ("R'G'B'A float"), in, layer, out, samples); + chroma_post_process (in, layer, mask, out, opacity, samples); + + return TRUE; +} diff --git a/app/operations/gimpoperationlchchromamode.h b/app/operations/gimpoperationlchchromamode.h new file mode 100644 index 0000000000..c38da569e0 --- /dev/null +++ b/app/operations/gimpoperationlchchromamode.h @@ -0,0 +1,72 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpoperationlchchromamode.h + * Copyright (C) 2015 Elle Stone + * Massimo Valentini + * Thomas Manni + * + * 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 . + */ + +#ifndef __GIMP_OPERATION_LCH_CHROMA_MODE_H__ +#define __GIMP_OPERATION_LCH_CHROMA_MODE_H__ + + +#include "gimpoperationpointlayermode.h" + + +#define GIMP_TYPE_OPERATION_LCH_CHROMA_MODE (gimp_operation_lch_chroma_mode_get_type ()) +#define GIMP_OPERATION_LCH_CHROMA_MODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_OPERATION_LCH_CHROMA_MODE, GimpOperationLchChromaMode)) +#define GIMP_OPERATION_LCH_CHROMA_MODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_OPERATION_LCH_CHROMA_MODE, GimpOperationLchChromaModeClass)) +#define GIMP_IS_OPERATION_LCH_CHROMA_MODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_OPERATION_LCH_CHROMA_MODE)) +#define GIMP_IS_OPERATION_LCH_CHROMA_MODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_OPERATION_LCH_CHROMA_MODE)) +#define GIMP_OPERATION_LCH_CHROMA_MODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_OPERATION_LCH_CHROMA_MODE, GimpOperationLchChromaModeClass)) + + +typedef struct _GimpOperationLchChromaMode GimpOperationLchChromaMode; +typedef struct _GimpOperationLchChromaModeClass GimpOperationLchChromaModeClass; + +struct _GimpOperationLchChromaMode +{ + GimpOperationPointLayerMode parent_instance; +}; + +struct _GimpOperationLchChromaModeClass +{ + GimpOperationPointLayerModeClass parent_class; +}; + + +GType gimp_operation_lch_chroma_mode_get_type (void) G_GNUC_CONST; + +gboolean gimp_operation_lch_chroma_mode_process_pixels_linear (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level); + +gboolean gimp_operation_lch_chroma_mode_process_pixels (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level); + +#endif /* __GIMP_OPERATION_LCH_CHROMA_MODE_H__ */ diff --git a/app/operations/gimpoperationlchcolormode.c b/app/operations/gimpoperationlchcolormode.c new file mode 100644 index 0000000000..4344877c3d --- /dev/null +++ b/app/operations/gimpoperationlchcolormode.c @@ -0,0 +1,193 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpoperationlchcolormode.c + * Copyright (C) 2015 Elle Stone + * Massimo Valentini + * Thomas Manni + * + * 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 . + */ + + #include "config.h" + +#include +#include +#include + +#include "libgimpcolor/gimpcolor.h" + +#include "operations-types.h" + +#include "gimpoperationlchcolormode.h" + + +static gboolean gimp_operation_lch_color_mode_process (GeglOperation *operation, + void *in_buf, + void *aux_buf, + void *aux2_buf, + void *out_buf, + glong samples, + const GeglRectangle *roi, + gint level); + + +G_DEFINE_TYPE (GimpOperationLchColorMode, gimp_operation_lch_color_mode, + GIMP_TYPE_OPERATION_POINT_LAYER_MODE) + +#define parent_class gimp_operation_lch_color_mode_parent_class + + +static void +gimp_operation_lch_color_mode_class_init (GimpOperationLchColorModeClass *klass) +{ + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; + + operation_class = GEGL_OPERATION_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); + + operation_class->want_in_place = FALSE; + + gegl_operation_class_set_keys (operation_class, + "name", "gimp:lch-color-mode", + "description", "GIMP LCH color mode operation", + NULL); + + point_class->process = gimp_operation_lch_color_mode_process; +} + +static void +gimp_operation_lch_color_mode_init (GimpOperationLchColorMode *self) +{ +} + +static gboolean +gimp_operation_lch_color_mode_process (GeglOperation *operation, + void *in_buf, + void *aux_buf, + void *aux2_buf, + void *out_buf, + glong samples, + const GeglRectangle *roi, + gint level) +{ + GimpOperationPointLayerMode *gimp_op = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = gimp_op->opacity; + gboolean linear = gimp_op->linear; + + return (linear ? gimp_operation_lch_color_mode_process_pixels_linear : + gimp_operation_lch_color_mode_process_pixels) + (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, level); +} + +static void +color_pre_process (const Babl *format, + const gfloat *in, + const gfloat *layer, + gfloat *out, + glong samples) +{ + gfloat tmp[4 * samples], *layer_lab = tmp; + gint i; + + babl_process (babl_fish (format, "CIE L alpha float"), in, &out[2 * samples], samples); + babl_process (babl_fish (format, "CIE Lab alpha float"), layer, layer_lab, samples); + + for (i = 0; i < samples; ++i) + { + out[4 * i + 0] = out[2 * samples + 2 * i + 0]; + out[4 * i + 1] = layer_lab[4 * i + 1]; + out[4 * i + 2] = layer_lab[4 * i + 2]; + out[4 * i + 3] = out[2 * samples + 2 * i + 1]; + } + + babl_process (babl_fish ("CIE Lab alpha float", format), out, out, samples); +} + +static void +color_post_process (const gfloat *in, + const gfloat *layer, + const gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples) +{ + while (samples--) + { + gfloat comp_alpha, new_alpha; + + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= *mask++; + + new_alpha = in[ALPHA] + (1.0f - in[ALPHA]) * comp_alpha; + + if (comp_alpha && new_alpha) + { + gfloat ratio = comp_alpha / new_alpha; + + out[RED] = out[RED] * ratio + in[RED] * (1.0f - ratio); + out[GREEN] = out[GREEN] * ratio + in[GREEN] * (1.0f - ratio); + out[BLUE] = out[BLUE] * ratio + in[BLUE] * (1.0f - ratio); + } + else + { + gint b; + + for (b = RED; b < ALPHA; b++) + { + out[b] = in[b]; + } + } + + out[ALPHA] = in[ALPHA]; + + in += 4; + layer += 4; + out += 4; + } +} + +gboolean +gimp_operation_lch_color_mode_process_pixels_linear (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level) +{ + color_pre_process (babl_format ("RGBA float"), in, layer, out, samples); + color_post_process (in, layer, mask, out, opacity, samples); + + return TRUE; +} + +gboolean +gimp_operation_lch_color_mode_process_pixels (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level) +{ + color_pre_process (babl_format ("R'G'B'A float"), in, layer, out, samples); + color_post_process (in, layer, mask, out, opacity, samples); + + return TRUE; +} diff --git a/app/operations/gimpoperationlchcolormode.h b/app/operations/gimpoperationlchcolormode.h new file mode 100644 index 0000000000..fb73e0bd33 --- /dev/null +++ b/app/operations/gimpoperationlchcolormode.h @@ -0,0 +1,72 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpoperationlchcolormode.h + * Copyright (C) 2015 Elle Stone + * Massimo Valentini + * Thomas Manni + * + * 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 . + */ + +#ifndef __GIMP_OPERATION_LCH_COLOR_MODE_H__ +#define __GIMP_OPERATION_LCH_COLOR_MODE_H__ + + +#include "gimpoperationpointlayermode.h" + + +#define GIMP_TYPE_OPERATION_LCH_COLOR_MODE (gimp_operation_lch_color_mode_get_type ()) +#define GIMP_OPERATION_LCH_COLOR_MODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_OPERATION_LCH_COLOR_MODE, GimpOperationLchColorMode)) +#define GIMP_OPERATION_LCH_COLOR_MODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_OPERATION_LCH_COLOR_MODE, GimpOperationLchColorModeClass)) +#define GIMP_IS_OPERATION_LCH_COLOR_MODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_OPERATION_LCH_COLOR_MODE)) +#define GIMP_IS_OPERATION_LCH_COLOR_MODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_OPERATION_LCH_COLOR_MODE)) +#define GIMP_OPERATION_LCH_COLOR_MODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_OPERATION_LCH_COLOR_MODE, GimpOperationLchColorModeClass)) + + +typedef struct _GimpOperationLchColorMode GimpOperationLchColorMode; +typedef struct _GimpOperationLchColorModeClass GimpOperationLchColorModeClass; + +struct _GimpOperationLchColorMode +{ + GimpOperationPointLayerMode parent_instance; +}; + +struct _GimpOperationLchColorModeClass +{ + GimpOperationPointLayerModeClass parent_class; +}; + + +GType gimp_operation_lch_color_mode_get_type (void) G_GNUC_CONST; + +gboolean gimp_operation_lch_color_mode_process_pixels_linear (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level); + +gboolean gimp_operation_lch_color_mode_process_pixels (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level); + +#endif /* __GIMP_OPERATION_LCH_COLOR_MODE_H__ */ diff --git a/app/operations/gimpoperationlchhuemode.c b/app/operations/gimpoperationlchhuemode.c new file mode 100644 index 0000000000..fe7d1b4387 --- /dev/null +++ b/app/operations/gimpoperationlchhuemode.c @@ -0,0 +1,204 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpoperationlchhuemode.c + * Copyright (C) 2015 Elle Stone + * Massimo Valentini + * Thomas Manni + * + * 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 . + */ + + #include "config.h" + +#include +#include +#include + +#include "libgimpmath/gimpmath.h" + +#include "operations-types.h" + +#include "gimpoperationlchhuemode.h" + + +static gboolean gimp_operation_lch_hue_mode_process (GeglOperation *operation, + void *in_buf, + void *aux_buf, + void *aux2_buf, + void *out_buf, + glong samples, + const GeglRectangle *roi, + gint level); + + +G_DEFINE_TYPE (GimpOperationLchHueMode, gimp_operation_lch_hue_mode, + GIMP_TYPE_OPERATION_POINT_LAYER_MODE) + +#define parent_class gimp_operation_lch_hue_mode_parent_class + + +static void +gimp_operation_lch_hue_mode_class_init (GimpOperationLchHueModeClass *klass) +{ + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; + + operation_class = GEGL_OPERATION_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); + + operation_class->want_in_place = FALSE; + + gegl_operation_class_set_keys (operation_class, + "name", "gimp:lch-hue-mode", + "description", "GIMP LCH hue mode operation", + NULL); + + point_class->process = gimp_operation_lch_hue_mode_process; +} + +static void +gimp_operation_lch_hue_mode_init (GimpOperationLchHueMode *self) +{ +} + +static gboolean +gimp_operation_lch_hue_mode_process (GeglOperation *operation, + void *in_buf, + void *aux_buf, + void *aux2_buf, + void *out_buf, + glong samples, + const GeglRectangle *roi, + gint level) +{ + GimpOperationPointLayerMode *gimp_op = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = gimp_op->opacity; + gboolean linear = gimp_op->linear; + + return (linear ? gimp_operation_lch_hue_mode_process_pixels_linear : + gimp_operation_lch_hue_mode_process_pixels) + (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, level); +} + +static void +hue_pre_process (const Babl *format, + const gfloat *in, + const gfloat *layer, + gfloat *out, + glong samples) +{ + gint i; + gfloat tmp[4 * samples], *layer_lab = tmp; + + babl_process (babl_fish (format, "CIE Lab alpha float"), in, out, samples); + babl_process (babl_fish (format, "CIE Lab alpha float"), layer, layer_lab, samples); + + for (i = 0; i < samples; ++i) + { + gfloat A2 = layer_lab[4 * i + 1]; + gfloat B2 = layer_lab[4 * i + 2]; + gfloat c2 = hypot (A2, B2); + + if (c2 > 0.1) + { + gfloat A1 = out[4 * i + 1]; + gfloat B1 = out[4 * i + 2]; + gfloat c1 = hypot (A1, B1); + gfloat A = c1 * A2 / c2; + gfloat B = c1 * B2 / c2; + + out[4 * i + 1] = A; + out[4 * i + 2] = B; + } + } + + babl_process (babl_fish ("CIE Lab alpha float", format), out, out, samples); +} + +static void +hue_post_process (const gfloat *in, + const gfloat *layer, + const gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples) +{ + while (samples--) + { + gfloat comp_alpha, new_alpha; + + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= *mask++; + + new_alpha = in[ALPHA] + (1.0f - in[ALPHA]) * comp_alpha; + + if (comp_alpha && new_alpha) + { + gfloat ratio = comp_alpha / new_alpha; + + out[RED] = out[RED] * ratio + in[RED] * (1.0f - ratio); + out[GREEN] = out[GREEN] * ratio + in[GREEN] * (1.0f - ratio); + out[BLUE] = out[BLUE] * ratio + in[BLUE] * (1.0f - ratio); + } + else + { + gint b; + + for (b = RED; b < ALPHA; b++) + { + out[b] = in[b]; + } + } + + out[ALPHA] = in[ALPHA]; + + in += 4; + layer += 4; + out += 4; + } +} + +gboolean +gimp_operation_lch_hue_mode_process_pixels_linear (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level) +{ + hue_pre_process (babl_format ("RGBA float"), in, layer, out, samples); + hue_post_process (in, layer, mask, out, opacity, samples); + + return TRUE; +} + +gboolean +gimp_operation_lch_hue_mode_process_pixels (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level) +{ + hue_pre_process (babl_format ("R'G'B'A float"), in, layer, out, samples); + hue_post_process (in, layer, mask, out, opacity, samples); + + return TRUE; +} diff --git a/app/operations/gimpoperationlchhuemode.h b/app/operations/gimpoperationlchhuemode.h new file mode 100644 index 0000000000..c79ebe8623 --- /dev/null +++ b/app/operations/gimpoperationlchhuemode.h @@ -0,0 +1,72 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpoperationlchhuemode.h + * Copyright (C) 2015 Elle Stone + * Massimo Valentini + * Thomas Manni + * + * 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 . + */ + +#ifndef __GIMP_OPERATION_LCH_HUE_MODE_H__ +#define __GIMP_OPERATION_LCH_HUE_MODE_H__ + + +#include "gimpoperationpointlayermode.h" + + +#define GIMP_TYPE_OPERATION_LCH_HUE_MODE (gimp_operation_lch_hue_mode_get_type ()) +#define GIMP_OPERATION_LCH_HUE_MODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_OPERATION_LCH_HUE_MODE, GimpOperationLchHueMode)) +#define GIMP_OPERATION_LCH_HUE_MODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_OPERATION_LCH_HUE_MODE, GimpOperationLchHueModeClass)) +#define GIMP_IS_OPERATION_LCH_HUE_MODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_OPERATION_LCH_HUE_MODE)) +#define GIMP_IS_OPERATION_LCH_HUE_MODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_OPERATION_LCH_HUE_MODE)) +#define GIMP_OPERATION_LCH_HUE_MODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_OPERATION_LCH_HUE_MODE, GimpOperationLchHueModeClass)) + + +typedef struct _GimpOperationLchHueMode GimpOperationLchHueMode; +typedef struct _GimpOperationLchHueModeClass GimpOperationLchHueModeClass; + +struct _GimpOperationLchHueMode +{ + GimpOperationPointLayerMode parent_instance; +}; + +struct _GimpOperationLchHueModeClass +{ + GimpOperationPointLayerModeClass parent_class; +}; + + +GType gimp_operation_lch_hue_mode_get_type (void) G_GNUC_CONST; + +gboolean gimp_operation_lch_hue_mode_process_pixels_linear (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level); + +gboolean gimp_operation_lch_hue_mode_process_pixels (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level); + +#endif /* __GIMP_OPERATION_LCH_HUE_MODE_H__ */ diff --git a/app/operations/gimpoperationlchlightnessmode.c b/app/operations/gimpoperationlchlightnessmode.c new file mode 100644 index 0000000000..3c7f44fd1d --- /dev/null +++ b/app/operations/gimpoperationlchlightnessmode.c @@ -0,0 +1,187 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpoperationlchlightnessmode.c + * Copyright (C) 2015 Elle Stone + * Massimo Valentini + * Thomas Manni + * + * 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 . + */ + + #include "config.h" + +#include +#include +#include + +#include "libgimpcolor/gimpcolor.h" + +#include "operations-types.h" + +#include "gimpoperationlchlightnessmode.h" + + +static gboolean gimp_operation_lch_lightness_mode_process (GeglOperation *operation, + void *in_buf, + void *aux_buf, + void *aux2_buf, + void *out_buf, + glong samples, + const GeglRectangle *roi, + gint level); + +G_DEFINE_TYPE (GimpOperationLchLightnessMode, gimp_operation_lch_lightness_mode, + GIMP_TYPE_OPERATION_POINT_LAYER_MODE) + +#define parent_class gimp_operation_lch_lightness_mode_parent_class + + +static void +gimp_operation_lch_lightness_mode_class_init (GimpOperationLchLightnessModeClass *klass) +{ + GeglOperationClass *operation_class; + GeglOperationPointComposer3Class *point_class; + + operation_class = GEGL_OPERATION_CLASS (klass); + point_class = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass); + + operation_class->want_in_place = FALSE; + + gegl_operation_class_set_keys (operation_class, + "name", "gimp:lch-lightness-mode", + "description", "GIMP LCH lightness mode operation", + NULL); + + point_class->process = gimp_operation_lch_lightness_mode_process; +} + +static void +gimp_operation_lch_lightness_mode_init (GimpOperationLchLightnessMode *self) +{ +} + +static gboolean +gimp_operation_lch_lightness_mode_process (GeglOperation *operation, + void *in_buf, + void *aux_buf, + void *aux2_buf, + void *out_buf, + glong samples, + const GeglRectangle *roi, + gint level) +{ + GimpOperationPointLayerMode *gimp_op = GIMP_OPERATION_POINT_LAYER_MODE (operation); + gfloat opacity = gimp_op->opacity; + gboolean linear = gimp_op->linear; + + return (linear ? gimp_operation_lch_lightness_mode_process_pixels_linear : + gimp_operation_lch_lightness_mode_process_pixels) + (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, level); +} + +static void +lightness_pre_process (const Babl *format, + const gfloat *in, + const gfloat *layer, + gfloat *out, + glong samples) +{ + gfloat tmp[2 * samples], *layer_lab = tmp; + gint i; + + babl_process (babl_fish (format, "CIE Lab alpha float"), in, out, samples); + babl_process (babl_fish (format, "CIE L alpha float"), layer, layer_lab, samples); + + for (i = 0; i < samples; ++i) + out[4 * i] = layer_lab[2 * i]; + + babl_process (babl_fish ("CIE Lab alpha float", format), out, out, samples); +} + +static void +lightness_post_process (const gfloat *in, + const gfloat *layer, + const gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples) +{ + while (samples--) + { + gfloat comp_alpha, new_alpha; + + comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity; + if (mask) + comp_alpha *= *mask++; + + new_alpha = in[ALPHA] + (1.0f - in[ALPHA]) * comp_alpha; + + if (comp_alpha && new_alpha) + { + gfloat ratio = comp_alpha / new_alpha; + + out[RED] = out[RED] * ratio + in[RED] * (1.0f - ratio); + out[GREEN] = out[GREEN] * ratio + in[GREEN] * (1.0f - ratio); + out[BLUE] = out[BLUE] * ratio + in[BLUE] * (1.0f - ratio); + } + else + { + gint b; + + for (b = RED; b < ALPHA; b++) + { + out[b] = in[b]; + } + } + + out[ALPHA] = in[ALPHA]; + + in += 4; + layer += 4; + out += 4; + } +} + +gboolean +gimp_operation_lch_lightness_mode_process_pixels_linear (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level) +{ + lightness_pre_process (babl_format ("RGBA float"), in, layer, out, samples); + lightness_post_process (in, layer, mask, out, opacity, samples); + + return TRUE; +} + +gboolean +gimp_operation_lch_lightness_mode_process_pixels (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level) +{ + lightness_pre_process (babl_format ("R'G'B'A float"), in, layer, out, samples); + lightness_post_process (in, layer, mask, out, opacity, samples); + + return TRUE; +} diff --git a/app/operations/gimpoperationlchlightnessmode.h b/app/operations/gimpoperationlchlightnessmode.h new file mode 100644 index 0000000000..834f16a280 --- /dev/null +++ b/app/operations/gimpoperationlchlightnessmode.h @@ -0,0 +1,72 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpoperationlchlightnessmode.h + * Copyright (C) 2015 Elle Stone + * Massimo Valentini + * Thomas Manni + * + * 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 . + */ + +#ifndef __GIMP_OPERATION_LCH_LIGHTNESS_MODE_H__ +#define __GIMP_OPERATION_LCH_LIGHTNESS_MODE_H__ + + +#include "gimpoperationpointlayermode.h" + + +#define GIMP_TYPE_OPERATION_LCH_LIGHTNESS_MODE (gimp_operation_lch_lightness_mode_get_type ()) +#define GIMP_OPERATION_LCH_LIGHTNESS_MODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_OPERATION_LCH_LIGHTNESS_MODE, GimpOperationLchLightnessMode)) +#define GIMP_OPERATION_LCH_LIGHTNESS_MODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_OPERATION_LCH_LIGHTNESS_MODE, GimpOperationLchLightnessModeClass)) +#define GIMP_IS_OPERATION_LCH_LIGHTNESS_MODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_OPERATION_LCH_LIGHTNESS_MODE)) +#define GIMP_IS_OPERATION_LCH_LIGHTNESS_MODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_OPERATION_LCH_LIGHTNESS_MODE)) +#define GIMP_OPERATION_LCH_LIGHTNESS_MODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_OPERATION_LCH_LIGHTNESS_MODE, GimpOperationLchLightnessModeClass)) + + +typedef struct _GimpOperationLchLightnessMode GimpOperationLchLightnessMode; +typedef struct _GimpOperationLchLightnessModeClass GimpOperationLchLightnessModeClass; + +struct _GimpOperationLchLightnessMode +{ + GimpOperationPointLayerMode parent_instance; +}; + +struct _GimpOperationLchLightnessModeClass +{ + GimpOperationPointLayerModeClass parent_class; +}; + + +GType gimp_operation_lch_lightness_mode_get_type (void) G_GNUC_CONST; + +gboolean gimp_operation_lch_lightness_mode_process_pixels_linear (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level); + +gboolean gimp_operation_lch_lightness_mode_process_pixels (gfloat *in, + gfloat *layer, + gfloat *mask, + gfloat *out, + gfloat opacity, + glong samples, + const GeglRectangle *roi, + gint level); + +#endif /* __GIMP_OPERATION_LCH_LIGHTNESS_MODE_H__ */ diff --git a/app/paint/gimppaintcore-loops.c b/app/paint/gimppaintcore-loops.c index a9c0dcba92..5be3474e9e 100644 --- a/app/paint/gimppaintcore-loops.c +++ b/app/paint/gimppaintcore-loops.c @@ -296,7 +296,7 @@ do_layer_blend (GeglBuffer *src_buffer, const guint paint_stride = gimp_temp_buf_get_width (paint_buf); gfloat *paint_data = (gfloat *) gimp_temp_buf_get_data (paint_buf); - GimpLayerModeFunction apply_func = get_layer_mode_function (paint_mode); + GimpLayerModeFunction apply_func = get_layer_mode_function (paint_mode, linear_mode); if (linear_mode) iterator_format = babl_format ("RGBA float"); diff --git a/app/widgets/gimpwidgets-constructors.c b/app/widgets/gimpwidgets-constructors.c index 53cfc00d3b..e799147d9c 100644 --- a/app/widgets/gimpwidgets-constructors.c +++ b/app/widgets/gimpwidgets-constructors.c @@ -103,7 +103,7 @@ gimp_paint_mode_menu_new (gboolean with_behind_mode, GtkWidget *combo; store = gimp_enum_store_new_with_values (GIMP_TYPE_LAYER_MODE_EFFECTS, - 21, + 25, GIMP_NORMAL_MODE, GIMP_DISSOLVE_MODE, @@ -129,7 +129,12 @@ gimp_paint_mode_menu_new (gboolean with_behind_mode, GIMP_HUE_MODE, GIMP_SATURATION_MODE, GIMP_COLOR_MODE, - GIMP_VALUE_MODE); + GIMP_VALUE_MODE, + + GIMP_LCH_HUE_MODE, + GIMP_LCH_CHROMA_MODE, + GIMP_LCH_COLOR_MODE, + GIMP_LCH_LIGHTNESS_MODE); gimp_int_store_insert_separator_after (GIMP_INT_STORE (store), GIMP_DISSOLVE_MODE, -1); @@ -146,6 +151,9 @@ gimp_paint_mode_menu_new (gboolean with_behind_mode, gimp_int_store_insert_separator_after (GIMP_INT_STORE (store), GIMP_DIVIDE_MODE, -1); + gimp_int_store_insert_separator_after (GIMP_INT_STORE (store), + GIMP_VALUE_MODE, -1); + if (with_behind_mode) { gimp_enum_store_insert_value_after (GIMP_ENUM_STORE (store), diff --git a/devel-docs/libgimp/tmpl/gimpenums.sgml b/devel-docs/libgimp/tmpl/gimpenums.sgml index 6490ec850b..2a2c98f3e6 100644 --- a/devel-docs/libgimp/tmpl/gimpenums.sgml +++ b/devel-docs/libgimp/tmpl/gimpenums.sgml @@ -95,4 +95,8 @@ gimpenums @GIMP_GRAIN_MERGE_MODE: @GIMP_COLOR_ERASE_MODE: @GIMP_NEW_OVERLAY_MODE: +@GIMP_LCH_HUE_MODE: +@GIMP_LCH_CHROMA_MODE: +@GIMP_LCH_COLOR_MODE: +@GIMP_LCH_LIGHTNESS_MODE: diff --git a/libgimp/gimpenums.h b/libgimp/gimpenums.h index 4a1a3d8bfd..4734b3a4b9 100644 --- a/libgimp/gimpenums.h +++ b/libgimp/gimpenums.h @@ -91,7 +91,11 @@ typedef enum GIMP_GRAIN_EXTRACT_MODE, GIMP_GRAIN_MERGE_MODE, GIMP_COLOR_ERASE_MODE, - GIMP_NEW_OVERLAY_MODE + GIMP_NEW_OVERLAY_MODE, + GIMP_LCH_HUE_MODE, + GIMP_LCH_CHROMA_MODE, + GIMP_LCH_COLOR_MODE, + GIMP_LCH_LIGHTNESS_MODE } GimpLayerModeEffects; diff --git a/tools/pdbgen/enums.pl b/tools/pdbgen/enums.pl index e06e71fc96..e6322586e1 100644 --- a/tools/pdbgen/enums.pl +++ b/tools/pdbgen/enums.pl @@ -638,7 +638,9 @@ package Gimp::CodeGen::enums; GIMP_BURN_MODE GIMP_HARDLIGHT_MODE GIMP_SOFTLIGHT_MODE GIMP_GRAIN_EXTRACT_MODE GIMP_GRAIN_MERGE_MODE GIMP_COLOR_ERASE_MODE - GIMP_NEW_OVERLAY_MODE) ], + GIMP_NEW_OVERLAY_MODE GIMP_LCH_HUE_MODE + GIMP_LCH_CHROMA_MODE GIMP_LCH_COLOR_MODE + GIMP_LCH_LIGHTNESS_MODE) ], mapping => { GIMP_NORMAL_MODE => '0', GIMP_DISSOLVE_MODE => '1', GIMP_BEHIND_MODE => '2', @@ -662,7 +664,11 @@ package Gimp::CodeGen::enums; GIMP_GRAIN_EXTRACT_MODE => '20', GIMP_GRAIN_MERGE_MODE => '21', GIMP_COLOR_ERASE_MODE => '22', - GIMP_NEW_OVERLAY_MODE => '23' } + GIMP_NEW_OVERLAY_MODE => '23', + GIMP_LCH_HUE_MODE => '24', + GIMP_LCH_CHROMA_MODE => '25', + GIMP_LCH_COLOR_MODE => '26', + GIMP_LCH_LIGHTNESS_MODE => '27' } }, GimpBrushApplicationMode => { contig => 1,