gimp r27268 - in trunk: . app/paint-funcs
- From: neo svn gnome org
- To: svn-commits-list gnome org
- Subject: gimp r27268 - in trunk: . app/paint-funcs
- Date: Mon, 13 Oct 2008 18:51:32 +0000 (UTC)
Author: neo
Date: Mon Oct 13 18:51:32 2008
New Revision: 27268
URL: http://svn.gnome.org/viewvc/gimp?rev=27268&view=rev
Log:
2008-10-13 Sven Neumann <sven gimp org>
Bug 547967 â Improve app/paint-funcs/ maintainability
Applied patch from Luidnel Maignan that splits the legacy code
for
layer modes into new files.
* app/paint-funcs/Makefile.am
* app/paint-funcs/layer-modes.[ch]
* app/paint-funcs/paint-funcs-utils.h: new files with code taken
from ...
* app/paint-funcs/paint-funcs-generic.h
* app/paint-funcs/paint-funcs.c: ... these two files.
Added:
trunk/app/paint-funcs/layer-modes.c
trunk/app/paint-funcs/layer-modes.h
trunk/app/paint-funcs/paint-funcs-utils.h
Modified:
trunk/ChangeLog
trunk/app/paint-funcs/Makefile.am
trunk/app/paint-funcs/paint-funcs-generic.h
trunk/app/paint-funcs/paint-funcs.c
Modified: trunk/app/paint-funcs/Makefile.am
==============================================================================
--- trunk/app/paint-funcs/Makefile.am (original)
+++ trunk/app/paint-funcs/Makefile.am Mon Oct 13 18:51:32 2008
@@ -19,10 +19,13 @@
noinst_LIBRARIES = libapppaint-funcs.a
libapppaint_funcs_a_SOURCES = \
- paint-funcs-types.h \
+ layer-modes.c \
+ layer-modes.h \
paint-funcs.c \
paint-funcs.h \
paint-funcs-generic.h \
+ paint-funcs-types.h \
+ paint-funcs-utils.h \
reduce-region.c \
reduce-region.h \
scale-region.c \
Added: trunk/app/paint-funcs/layer-modes.c
==============================================================================
--- (empty file)
+++ trunk/app/paint-funcs/layer-modes.c Mon Oct 13 18:51:32 2008
@@ -0,0 +1,1112 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "libgimpcolor/gimpcolor.h"
+
+#include "paint-funcs-types.h"
+
+#include "layer-modes.h"
+#include "paint-funcs-utils.h"
+
+
+#define RANDOM_SEED 314159265
+#define RANDOM_TABLE_SIZE 4096
+
+static guchar add_lut[511];
+static gint32 random_table[RANDOM_TABLE_SIZE];
+
+
+/** FIXME: should be static inline **/
+void
+dissolve_pixels (const guchar *src,
+ const guchar *mask,
+ guchar *dest,
+ gint x,
+ gint y,
+ gint opacity,
+ gint length,
+ gint sb,
+ gint db,
+ gboolean has_alpha)
+{
+ const gint alpha = db - 1;
+ gint b;
+ GRand *gr;
+
+ gr = g_rand_new_with_seed (random_table[y % RANDOM_TABLE_SIZE]);
+
+ /* Ignore x random values so we get a deterministic result */
+ for (b = 0; b < x; b ++)
+ g_rand_int (gr);
+
+ while (length--)
+ {
+ gint combined_opacity;
+ gint32 rand_val;
+
+ /* preserve the intensity values */
+ for (b = 0; b < alpha; b++)
+ dest[b] = src[b];
+
+ /* dissolve if random value is >= opacity */
+ rand_val = g_rand_int_range (gr, 0, 255);
+
+ if (mask)
+ {
+ if (has_alpha)
+ combined_opacity = opacity * src[alpha] * *mask / (255 * 255);
+ else
+ combined_opacity = opacity * *mask / 255;
+
+ mask++;
+ }
+ else
+ {
+ if (has_alpha)
+ combined_opacity = opacity * src[alpha] / 255;
+ else
+ combined_opacity = opacity;
+ }
+
+ dest[alpha] = (rand_val >= combined_opacity) ? 0 : OPAQUE_OPACITY;
+
+ src += sb;
+ dest += db;
+ }
+
+ g_rand_free (gr);
+
+}
+
+static inline void
+multiply_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+ const guint alpha = ((has_alpha1 || has_alpha2) ?
+ MAX (bytes1, bytes2) - 1 : bytes1);
+
+ if (has_alpha1 && has_alpha2)
+ {
+ while (length --)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ guint tmp;
+
+ dest[b] = INT_MULT(src1[b], src2[b], tmp);
+ }
+
+ dest[alpha] = MIN (src1[alpha], src2[alpha]);
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+ }
+ else if (has_alpha2)
+ {
+ while (length --)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ guint tmp;
+
+ dest[b] = INT_MULT(src1[b], src2[b], tmp);
+ }
+
+ dest[alpha] = src2[alpha];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+ }
+ else
+ {
+ while (length --)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ guint tmp;
+
+ dest[b] = INT_MULT (src1[b], src2[b], tmp);
+ }
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+ }
+}
+
+static inline void
+divide_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+ const guint alpha = ((has_alpha1 || has_alpha2) ?
+ MAX (bytes1, bytes2) - 1 : bytes1);
+ while (length--)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ guint result = ((src1[b] * 256) / (1 + src2[b]));
+
+ dest[b] = MIN (result, 255);
+ }
+
+ if (has_alpha1 && has_alpha2)
+ dest[alpha] = MIN (src1[alpha], src2[alpha]);
+ else if (has_alpha2)
+ dest[alpha] = src2[alpha];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+
+static inline void
+screen_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+ const guint alpha = ((has_alpha1 || has_alpha2) ?
+ MAX (bytes1, bytes2) - 1 : bytes1);
+
+ while (length --)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ guint tmp;
+
+ dest[b] = 255 - INT_MULT((255 - src1[b]), (255 - src2[b]), tmp);
+ }
+
+ if (has_alpha1 && has_alpha2)
+ dest[alpha] = MIN (src1[alpha], src2[alpha]);
+ else if (has_alpha2)
+ dest[alpha] = src2[alpha];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+
+static inline void
+overlay_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+ const guint alpha = ((has_alpha1 || has_alpha2) ?
+ MAX (bytes1, bytes2) - 1 : bytes1);
+
+ while (length --)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ guint tmp, tmpM;
+
+ dest[b] = INT_MULT(src1[b], src1[b] + INT_MULT (2 * src2[b],
+ 255 - src1[b],
+ tmpM), tmp);
+ }
+
+ if (has_alpha1 && has_alpha2)
+ dest[alpha] = MIN (src1[alpha], src2[alpha]);
+ else if (has_alpha2)
+ dest[alpha] = src2[alpha];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+static inline void
+difference_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+ const guint alpha = ((has_alpha1 || has_alpha2) ?
+ MAX (bytes1, bytes2) - 1 : bytes1);
+
+ while (length --)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ gint diff = src1[b] - src2[b];
+
+ dest[b] = (diff < 0) ? -diff : diff;
+ }
+
+ if (has_alpha1 && has_alpha2)
+ dest[alpha] = MIN (src1[alpha], src2[alpha]);
+ else if (has_alpha2)
+ dest[alpha] = src2[alpha];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+static inline void
+add_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+ const guint alpha = ((has_alpha1 || has_alpha2) ?
+ MAX (bytes1, bytes2) - 1 : bytes1);
+
+ while (length --)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ dest[b] = add_lut[src1[b] + src2[b]];
+
+ if (has_alpha1 && has_alpha2)
+ dest[alpha] = MIN (src1[alpha], src2[alpha]);
+ else if (has_alpha2)
+ dest[alpha] = src2[alpha];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+
+static inline void
+subtract_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+ const guint alpha = ((has_alpha1 || has_alpha2) ?
+ MAX (bytes1, bytes2) - 1 : bytes1);
+
+ while (length --)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ gint diff = src1[b] - src2[b];
+
+ dest[b] = (diff < 0) ? 0 : diff;
+ }
+
+ if (has_alpha1 && has_alpha2)
+ dest[alpha] = MIN (src1[alpha], src2[alpha]);
+ else if (has_alpha2)
+ dest[alpha] = src2[alpha];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+static inline void
+darken_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+ const guint alpha = ((has_alpha1 || has_alpha2) ?
+ MAX (bytes1, bytes2) - 1 : bytes1);
+
+ while (length--)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ guchar s1 = src1[b];
+ guchar s2 = src2[b];
+
+ dest[b] = (s1 < s2) ? s1 : s2;
+ }
+
+ if (has_alpha1 && has_alpha2)
+ dest[alpha] = MIN (src1[alpha], src2[alpha]);
+ else if (has_alpha2)
+ dest[alpha] = src2[alpha];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+
+static inline void
+lighten_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+ const guint alpha = ((has_alpha1 || has_alpha2) ?
+ MAX (bytes1, bytes2) - 1 : bytes1);
+
+ while (length--)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ guchar s1 = src1[b];
+ guchar s2 = src2[b];
+
+ dest[b] = (s1 < s2) ? s2 : s1;
+ }
+
+ if (has_alpha1 && has_alpha2)
+ dest[alpha] = MIN (src1[alpha], src2[alpha]);
+ else if (has_alpha2)
+ dest[alpha] = src2[alpha];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+
+static inline void
+hue_only_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+
+ /* assumes inputs are only 4 byte RGBA pixels */
+ while (length--)
+ {
+ gint r1, g1, b1;
+ gint r2, g2, b2;
+
+ r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
+ r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
+
+ gimp_rgb_to_hsv_int (&r1, &g1, &b1);
+ gimp_rgb_to_hsv_int (&r2, &g2, &b2);
+
+ r1 = r2;
+
+ /* set the destination */
+ gimp_hsv_to_rgb_int (&r1, &g1, &b1);
+
+ dest[0] = r1; dest[1] = g1; dest[2] = b1;
+
+ if (has_alpha1 && has_alpha2)
+ dest[3] = MIN (src1[3], src2[3]);
+ else if (has_alpha2)
+ dest[3] = src2[3];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+
+static inline void
+saturation_only_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+
+ /* assumes inputs are only 4 byte RGBA pixels */
+ while (length--)
+ {
+ gint r1, g1, b1;
+ gint r2, g2, b2;
+
+ r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
+ r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
+
+ gimp_rgb_to_hsv_int (&r1, &g1, &b1);
+ gimp_rgb_to_hsv_int (&r2, &g2, &b2);
+
+ g1 = g2;
+
+ /* set the destination */
+ gimp_hsv_to_rgb_int (&r1, &g1, &b1);
+
+ dest[0] = r1; dest[1] = g1; dest[2] = b1;
+
+ if (has_alpha1 && has_alpha2)
+ dest[3] = MIN (src1[3], src2[3]);
+ else if (has_alpha2)
+ dest[3] = src2[3];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+
+static inline void
+value_only_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+
+ /* assumes inputs are only 4 byte RGBA pixels */
+ while (length--)
+ {
+ gint r1, g1, b1;
+ gint r2, g2, b2;
+
+ r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
+ r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
+
+ gimp_rgb_to_hsv_int (&r1, &g1, &b1);
+ gimp_rgb_to_hsv_int (&r2, &g2, &b2);
+
+ b1 = b2;
+
+ /* set the destination */
+ gimp_hsv_to_rgb_int (&r1, &g1, &b1);
+
+ dest[0] = r1; dest[1] = g1; dest[2] = b1;
+
+ if (has_alpha1 && has_alpha2)
+ dest[3] = MIN (src1[3], src2[3]);
+ else if (has_alpha2)
+ dest[3] = src2[3];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+
+static inline void
+color_only_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+
+ /* assumes inputs are only 4 byte RGBA pixels */
+ while (length--)
+ {
+ gint r1, g1, b1;
+ gint r2, g2, b2;
+
+ r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
+ r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
+
+ gimp_rgb_to_hsl_int (&r1, &g1, &b1);
+ gimp_rgb_to_hsl_int (&r2, &g2, &b2);
+
+ /* transfer hue and saturation to the source pixel */
+ r1 = r2;
+ g1 = g2;
+
+ /* set the destination */
+ gimp_hsl_to_rgb_int (&r1, &g1, &b1);
+
+ dest[0] = r1; dest[1] = g1; dest[2] = b1;
+
+ if (has_alpha1 && has_alpha2)
+ dest[3] = MIN (src1[3], src2[3]);
+ else if (has_alpha2)
+ dest[3] = src2[3];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+static inline void
+dodge_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+ const guint alpha = ((has_alpha1 || has_alpha2) ?
+ MAX (bytes1, bytes2) - 1 : bytes1);
+ while (length --)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ guint tmp;
+
+ tmp = src1[b] << 8;
+ tmp /= 256 - src2[b];
+
+ dest[b] = (guchar) MIN (tmp, 255);
+ }
+
+ if (has_alpha1 && has_alpha2)
+ dest[alpha] = MIN (src1[alpha], src2[alpha]);
+ else if (has_alpha2)
+ dest[alpha] = src2[alpha];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+
+static inline void
+burn_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+ const guint alpha = ((has_alpha1 || has_alpha2) ?
+ MAX (bytes1, bytes2) - 1 : bytes1);
+
+ while (length --)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ /* FIXME: Is the burn effect supposed to be dependant on the sign
+ * of this temporary variable?
+ */
+ gint tmp;
+
+ tmp = (255 - src1[b]) << 8;
+ tmp /= src2[b] + 1;
+
+ dest[b] = (guchar) CLAMP (255 - tmp, 0, 255);
+ }
+
+ if (has_alpha1 && has_alpha2)
+ dest[alpha] = MIN (src1[alpha], src2[alpha]);
+ else if (has_alpha2)
+ dest[alpha] = src2[alpha];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+
+static inline void
+hardlight_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+ const guint alpha = ((has_alpha1 || has_alpha2) ?
+ MAX (bytes1, bytes2) - 1 : bytes1);
+
+ while (length --)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ guint tmp;
+
+ if (src2[b] > 128)
+ {
+ tmp = (((gint)255 - src1[b]) *
+ ((gint)255 - ((src2[b] - 128) << 1)));
+ dest[b] = (guchar) MIN (255 - (tmp >> 8), 255);
+ }
+ else
+ {
+ tmp = (gint) src1[b] * ((gint)src2[b] << 1);
+ dest[b] = (guchar) MIN (tmp >> 8, 255);
+ }
+ }
+
+ if (has_alpha1 && has_alpha2)
+ dest[alpha] = MIN (src1[alpha], src2[alpha]);
+ else if (has_alpha2)
+ dest[alpha] = src2[alpha];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+
+static inline void
+softlight_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+ const guint alpha = ((has_alpha1 || has_alpha2) ?
+ MAX (bytes1, bytes2) - 1 : bytes1);
+
+ while (length --)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ guint tmp1, tmp2, tmp3;
+
+ /* Mix multiply and screen */
+ guint tmpM = INT_MULT (src1[b], src2[b], tmpM);
+ guint tmpS = 255 - INT_MULT((255 - src1[b]), (255 - src2[b]), tmp1);
+
+ dest[b] = INT_MULT ((255 - src1[b]), tmpM, tmp2) +
+ INT_MULT (src1[b], tmpS, tmp3);
+ }
+
+ if (has_alpha1 && has_alpha2)
+ dest[alpha] = MIN (src1[alpha], src2[alpha]);
+ else if (has_alpha2)
+ dest[alpha] = src2[alpha];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+
+static inline void
+grain_extract_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+ const guint alpha = ((has_alpha1 || has_alpha2) ?
+ MAX (bytes1, bytes2) - 1 : bytes1);
+
+ while (length --)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ gint diff = src1[b] - src2[b] + 128;
+
+ dest[b] = (guchar) CLAMP (diff, 0, 255);
+ }
+
+ if (has_alpha1 && has_alpha2)
+ dest[alpha] = MIN (src1[alpha], src2[alpha]);
+ else if (has_alpha2)
+ dest[alpha] = src2[alpha];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+
+static inline void
+grain_merge_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guint length,
+ guint bytes1,
+ guint bytes2)
+{
+ const guint has_alpha1 = HAS_ALPHA (bytes1);
+ const guint has_alpha2 = HAS_ALPHA (bytes2);
+ const guint alpha = ((has_alpha1 || has_alpha2) ?
+ MAX (bytes1, bytes2) - 1 : bytes1);
+
+ while (length --)
+ {
+ guint b;
+
+ for (b = 0; b < alpha; b++)
+ {
+ /* Add, re-center and clip. */
+ gint sum = src1[b] + src2[b] - 128;
+
+ dest[b] = (guchar) CLAMP (sum, 0, 255);
+ }
+
+ if (has_alpha1 && has_alpha2)
+ dest[alpha] = MIN (src1[alpha], src2[alpha]);
+ else if (has_alpha2)
+ dest[alpha] = src2[alpha];
+
+ src1 += bytes1;
+ src2 += bytes2;
+ dest += bytes2;
+ }
+}
+
+
+
+/**********************************
+ * Layer mode interface functions *
+ **********************************/
+
+void
+layer_modes_setup (void)
+{
+ GRand *gr;
+ gint i;
+
+ /* generate a table of random seeds */
+ gr = g_rand_new_with_seed (RANDOM_SEED);
+
+ for (i = 0; i < RANDOM_TABLE_SIZE; i++)
+ random_table[i] = g_rand_int (gr);
+
+ for (i = 0; i < 256; i++)
+ add_lut[i] = i;
+
+ for (i = 256; i <= 510; i++)
+ add_lut[i] = 255;
+
+ g_rand_free (gr);
+}
+
+void
+layer_normal_mode (struct apply_layer_mode_struct *alms)
+{
+ /* assumes we're applying src2 TO src1 */
+ *(alms->dest) = alms->src2;
+}
+
+void
+layer_dissolve_mode (struct apply_layer_mode_struct *alms)
+{
+ const guint has_alpha1 = HAS_ALPHA (alms->bytes1);
+ const guint has_alpha2 = HAS_ALPHA (alms->bytes2);
+ guint dest_bytes;
+
+ /* Since dissolve requires an alpha channel... */
+ if (has_alpha2)
+ dest_bytes = alms->bytes2;
+ else
+ dest_bytes = alms->bytes2 + 1;
+
+ dissolve_pixels (alms->src2, alms->mask, *(alms->dest),
+ alms->x, alms->y,
+ alms->opacity, alms->length,
+ alms->bytes2, dest_bytes,
+ has_alpha2);
+
+ alms->combine = has_alpha1 ? COMBINE_INTEN_A_INTEN_A : COMBINE_INTEN_INTEN_A;
+}
+
+void
+layer_multiply_mode (struct apply_layer_mode_struct *alms)
+{
+ multiply_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+}
+
+void
+layer_divide_mode (struct apply_layer_mode_struct *alms)
+{
+ divide_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+}
+
+void
+layer_screen_mode (struct apply_layer_mode_struct *alms)
+{
+ screen_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+}
+
+void
+layer_overlay_mode (struct apply_layer_mode_struct *alms)
+{
+ overlay_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+}
+
+void
+layer_difference_mode (struct apply_layer_mode_struct *alms)
+{
+ difference_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+}
+
+void
+layer_addition_mode (struct apply_layer_mode_struct *alms)
+{
+ add_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+}
+
+void
+layer_subtract_mode (struct apply_layer_mode_struct *alms)
+{
+ subtract_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+}
+
+void
+layer_darken_only_mode (struct apply_layer_mode_struct *alms)
+{
+ darken_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+}
+
+void
+layer_lighten_only_mode (struct apply_layer_mode_struct *alms)
+{
+ lighten_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+}
+
+void
+layer_hue_mode (struct apply_layer_mode_struct *alms)
+{
+ /* only works on RGB color images */
+ if (alms->bytes1 > 2)
+ hue_only_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+ else
+ *(alms->dest) = alms->src2;
+}
+
+void
+layer_saturation_mode (struct apply_layer_mode_struct *alms)
+{
+ /* only works on RGB color images */
+ if (alms->bytes1 > 2)
+ saturation_only_pixels (alms->src1, alms->src2, *(alms->dest),
+ alms->length, alms->bytes1, alms->bytes2);
+ else
+ *(alms->dest) = alms->src2;
+}
+
+void
+layer_value_mode (struct apply_layer_mode_struct *alms)
+{
+ /* only works on RGB color images */
+ if (alms->bytes1 > 2)
+ value_only_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+ else
+ *(alms->dest) = alms->src2;
+}
+
+void
+layer_color_mode (struct apply_layer_mode_struct *alms)
+{
+ /* only works on RGB color images */
+ if (alms->bytes1 > 2)
+ color_only_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+ else
+ *(alms->dest) = alms->src2;
+}
+
+void
+layer_behind_mode (struct apply_layer_mode_struct *alms)
+{
+ *(alms->dest) = alms->src2;
+ if (HAS_ALPHA (alms->bytes1))
+ alms->combine = BEHIND_INTEN;
+ else
+ alms->combine = NO_COMBINATION;
+}
+
+void
+layer_replace_mode (struct apply_layer_mode_struct *alms)
+{
+ *(alms->dest) = alms->src2;
+ alms->combine = REPLACE_INTEN;
+}
+
+void
+layer_erase_mode (struct apply_layer_mode_struct *alms)
+{
+ *(alms->dest) = alms->src2;
+ /* If both sources have alpha channels, call erase function.
+ * Otherwise, just combine in the normal manner
+ */
+ alms->combine =
+ (HAS_ALPHA (alms->bytes1) && HAS_ALPHA (alms->bytes2)) ? ERASE_INTEN : 0;
+}
+
+void
+layer_anti_erase_mode (struct apply_layer_mode_struct *alms)
+{
+ *(alms->dest) = alms->src2;
+ alms->combine =
+ (HAS_ALPHA (alms->bytes1) && HAS_ALPHA (alms->bytes2)) ? ANTI_ERASE_INTEN : 0;
+}
+
+void
+layer_color_erase_mode (struct apply_layer_mode_struct *alms)
+{
+ *(alms->dest) = alms->src2;
+ alms->combine =
+ (HAS_ALPHA (alms->bytes1) && HAS_ALPHA (alms->bytes2)) ? COLOR_ERASE_INTEN : 0;
+}
+
+void
+layer_dodge_mode (struct apply_layer_mode_struct *alms)
+{
+ dodge_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+}
+
+void
+layer_burn_mode (struct apply_layer_mode_struct *alms)
+{
+ burn_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+}
+
+void
+layer_hardlight_mode (struct apply_layer_mode_struct *alms)
+{
+ hardlight_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+}
+
+void
+layer_softlight_mode (struct apply_layer_mode_struct *alms)
+{
+ softlight_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+}
+
+void
+layer_grain_extract_mode (struct apply_layer_mode_struct *alms)
+{
+ grain_extract_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+}
+
+void
+layer_grain_merge_mode (struct apply_layer_mode_struct *alms)
+{
+ grain_merge_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+ alms->bytes1, alms->bytes2);
+}
Added: trunk/app/paint-funcs/layer-modes.h
==============================================================================
--- (empty file)
+++ trunk/app/paint-funcs/layer-modes.h Mon Oct 13 18:51:32 2008
@@ -0,0 +1,81 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C); 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __LAYER_MODES_H__
+#define __LAYER_MODES_H__
+
+/* FIXME: This function should not be called directly but
+ * through layer_dissolve_mode function
+ */
+void dissolve_pixels (const guchar *src,
+ const guchar *mask,
+ guchar *dest,
+ gint x,
+ gint y,
+ gint opacity,
+ gint length,
+ gint sb,
+ gint db,
+ gboolean has_alpha);
+
+struct apply_layer_mode_struct
+{
+ guint bytes1 : 3;
+ guint bytes2 : 3;
+ guchar *src1;
+ guchar *src2;
+ const guchar *mask;
+ guchar **dest;
+ gint x;
+ gint y;
+ guint opacity;
+ guint length;
+ CombinationMode combine;
+};
+
+void layer_modes_setup (void);
+
+void layer_normal_mode (struct apply_layer_mode_struct *alms);
+void layer_dissolve_mode (struct apply_layer_mode_struct *alms);
+void layer_multiply_mode (struct apply_layer_mode_struct *alms);
+void layer_divide_mode (struct apply_layer_mode_struct *alms);
+void layer_screen_mode (struct apply_layer_mode_struct *alms);
+void layer_overlay_mode (struct apply_layer_mode_struct *alms);
+void layer_difference_mode (struct apply_layer_mode_struct *alms);
+void layer_addition_mode (struct apply_layer_mode_struct *alms);
+void layer_subtract_mode (struct apply_layer_mode_struct *alms);
+void layer_darken_only_mode (struct apply_layer_mode_struct *alms);
+void layer_lighten_only_mode (struct apply_layer_mode_struct *alms);
+void layer_hue_mode (struct apply_layer_mode_struct *alms);
+void layer_saturation_mode (struct apply_layer_mode_struct *alms);
+void layer_value_mode (struct apply_layer_mode_struct *alms);
+void layer_color_mode (struct apply_layer_mode_struct *alms);
+void layer_behind_mode (struct apply_layer_mode_struct *alms);
+void layer_replace_mode (struct apply_layer_mode_struct *alms);
+void layer_erase_mode (struct apply_layer_mode_struct *alms);
+void layer_anti_erase_mode (struct apply_layer_mode_struct *alms);
+void layer_color_erase_mode (struct apply_layer_mode_struct *alms);
+void layer_dodge_mode (struct apply_layer_mode_struct *alms);
+void layer_burn_mode (struct apply_layer_mode_struct *alms);
+void layer_hardlight_mode (struct apply_layer_mode_struct *alms);
+void layer_softlight_mode (struct apply_layer_mode_struct *alms);
+void layer_grain_extract_mode (struct apply_layer_mode_struct *alms);
+void layer_grain_merge_mode (struct apply_layer_mode_struct *alms);
+
+#endif
+
Modified: trunk/app/paint-funcs/paint-funcs-generic.h
==============================================================================
--- trunk/app/paint-funcs/paint-funcs-generic.h (original)
+++ trunk/app/paint-funcs/paint-funcs-generic.h Mon Oct 13 18:51:32 2008
@@ -25,49 +25,6 @@
#define __PAINT_FUNCS_GENERIC_H__
-#define INT_MULT(a,b,t) ((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8))
-
-/* This version of INT_MULT3 is very fast, but suffers from some
- slight roundoff errors. It returns the correct result 99.987
- percent of the time */
-#define INT_MULT3(a,b,c,t) ((t) = (a) * (b) * (c) + 0x7F5B, \
- ((((t) >> 7) + (t)) >> 16))
-/*
- This version of INT_MULT3 always gives the correct result, but runs at
- approximatly one third the speed. */
-/* #define INT_MULT3(a,b,c,t) (((a) * (b) * (c) + 32512) / 65025.0)
- */
-
-#define INT_BLEND(a,b,alpha,tmp) (INT_MULT((a) - (b), alpha, tmp) + (b))
-
-#define RANDOM_TABLE_SIZE 4096
-
-/* A drawable has an alphachannel if contains either 4 or 2 bytes data
- * aka GRAYA and RGBA and thus the macro below works. This will have
- * to change if we support bigger formats. We'll do it so for now because
- * masking is always cheaper than passing parameters over the stack. */
-/* FIXME: Move to a global place */
-#define HAS_ALPHA(bytes) (~bytes & 1)
-
-/* FIXME: Move to a more global place */
-struct apply_layer_mode_struct
-{
- guint bytes1 : 3;
- guint bytes2 : 3;
- guchar *src1;
- guchar *src2;
- const guchar *mask;
- guchar **dest;
- gint x;
- gint y;
- guint opacity;
- guint length;
- CombinationMode combine;
-};
-
-static guchar add_lut[511];
-static gint32 random_table[RANDOM_TABLE_SIZE];
-
void
color_pixels (guchar *dest,
const guchar *color,
@@ -255,988 +212,156 @@
for (i = 0; i < w; i++)
{
const guchar *p = pat + ((i + x) % pattern->width) * pattern->bytes;
- guint b;
-
- for (b = 0; b < alpha; b++)
- dest[b] = p[b];
-
- if (HAS_ALPHA (bytes))
- {
- if (mask)
- dest[alpha] = *mask++;
- else
- dest[alpha] = OPAQUE_OPACITY;
-
- if (HAS_ALPHA (pattern->bytes))
- dest[alpha] = (guchar) (dest[alpha] *
- p[alpha] / (gdouble) OPAQUE_OPACITY);
- }
-
- dest += bytes;
- }
-}
-
-/*
- * blend_pixels patched 8-24-05 to fix bug #163721. Note that this change
- * causes the function to treat src1 and src2 asymmetrically. This gives the
- * right behavior for the smudge tool, which is the only user of this function
- * at the time of patching. If you want to use the function for something
- * else, caveat emptor.
- */
-inline void
-blend_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guchar blend,
- guint w,
- guint bytes)
-{
- if (HAS_ALPHA (bytes))
- {
- const guint blend1 = 255 - blend;
- const guint blend2 = blend + 1;
- const guint c = bytes - 1;
-
- while (w--)
- {
- const gint a1 = blend1 * src1[c];
- const gint a2 = blend2 * src2[c];
- const gint a = a1 + a2;
- guint b;
-
- if (!a)
- {
- for (b = 0; b < bytes; b++)
- dest[b] = 0;
- }
- else
- {
- for (b = 0; b < c; b++)
- dest[b] =
- src1[b] + (src1[b] * a1 + src2[b] * a2 - a * src1[b]) / a;
-
- dest[c] = a >> 8;
- }
-
- src1 += bytes;
- src2 += bytes;
- dest += bytes;
- }
- }
- else
- {
- const guchar blend1 = 255 - blend;
-
- while (w--)
- {
- guint b;
-
- for (b = 0; b < bytes; b++)
- dest[b] =
- src1[b] + (src1[b] * blend1 + src2[b] * blend - src1[b] * 255) / 255;
-
- src1 += bytes;
- src2 += bytes;
- dest += bytes;
- }
- }
-}
-
-inline void
-shade_pixels (const guchar *src,
- guchar *dest,
- const guchar *col,
- guchar blend,
- guint w,
- guint bytes,
- gboolean has_alpha)
-{
- const guchar blend2 = (255 - blend);
- const guint alpha = (has_alpha) ? bytes - 1 : bytes;
-
- while (w--)
- {
- guint b;
-
- for (b = 0; b < alpha; b++)
- dest[b] = (src[b] * blend2 + col[b] * blend) / 255;
-
- if (has_alpha)
- dest[alpha] = src[alpha]; /* alpha channel */
-
- src += bytes;
- dest += bytes;
- }
-}
-
-
-inline void
-extract_alpha_pixels (const guchar *src,
- const guchar *mask,
- guchar *dest,
- guint w,
- guint bytes)
-{
- const guint alpha = bytes - 1;
-
- if (mask)
- {
- const guchar *m = mask;
-
- while (w--)
- {
- gint tmp;
-
- *dest++ = INT_MULT(src[alpha], *m, tmp);
- m++;
- src += bytes;
- }
- }
- else
- {
- while (w--)
- {
- gint tmp;
-
- *dest++ = INT_MULT(src[alpha], OPAQUE_OPACITY, tmp);
- src += bytes;
- }
- }
-}
-
-
-static inline void
-darken_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
- const guint alpha = ((has_alpha1 || has_alpha2) ?
- MAX (bytes1, bytes2) - 1 : bytes1);
-
- while (length--)
- {
- guint b;
-
- for (b = 0; b < alpha; b++)
- {
- guchar s1 = src1[b];
- guchar s2 = src2[b];
-
- dest[b] = (s1 < s2) ? s1 : s2;
- }
-
- if (has_alpha1 && has_alpha2)
- dest[alpha] = MIN (src1[alpha], src2[alpha]);
- else if (has_alpha2)
- dest[alpha] = src2[alpha];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
-}
-
-
-static inline void
-lighten_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
- const guint alpha = ((has_alpha1 || has_alpha2) ?
- MAX (bytes1, bytes2) - 1 : bytes1);
-
- while (length--)
- {
- guint b;
-
- for (b = 0; b < alpha; b++)
- {
- guchar s1 = src1[b];
- guchar s2 = src2[b];
-
- dest[b] = (s1 < s2) ? s2 : s1;
- }
-
- if (has_alpha1 && has_alpha2)
- dest[alpha] = MIN (src1[alpha], src2[alpha]);
- else if (has_alpha2)
- dest[alpha] = src2[alpha];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
-}
-
-
-static inline void
-hue_only_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
-
- /* assumes inputs are only 4 byte RGBA pixels */
- while (length--)
- {
- gint r1, g1, b1;
- gint r2, g2, b2;
-
- r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
- r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
-
- gimp_rgb_to_hsv_int (&r1, &g1, &b1);
- gimp_rgb_to_hsv_int (&r2, &g2, &b2);
-
- r1 = r2;
-
- /* set the destination */
- gimp_hsv_to_rgb_int (&r1, &g1, &b1);
-
- dest[0] = r1; dest[1] = g1; dest[2] = b1;
-
- if (has_alpha1 && has_alpha2)
- dest[3] = MIN (src1[3], src2[3]);
- else if (has_alpha2)
- dest[3] = src2[3];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
-}
-
-
-static inline void
-saturation_only_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
-
- /* assumes inputs are only 4 byte RGBA pixels */
- while (length--)
- {
- gint r1, g1, b1;
- gint r2, g2, b2;
-
- r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
- r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
-
- gimp_rgb_to_hsv_int (&r1, &g1, &b1);
- gimp_rgb_to_hsv_int (&r2, &g2, &b2);
-
- g1 = g2;
-
- /* set the destination */
- gimp_hsv_to_rgb_int (&r1, &g1, &b1);
-
- dest[0] = r1; dest[1] = g1; dest[2] = b1;
-
- if (has_alpha1 && has_alpha2)
- dest[3] = MIN (src1[3], src2[3]);
- else if (has_alpha2)
- dest[3] = src2[3];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
-}
-
-
-static inline void
-value_only_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
-
- /* assumes inputs are only 4 byte RGBA pixels */
- while (length--)
- {
- gint r1, g1, b1;
- gint r2, g2, b2;
-
- r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
- r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
-
- gimp_rgb_to_hsv_int (&r1, &g1, &b1);
- gimp_rgb_to_hsv_int (&r2, &g2, &b2);
-
- b1 = b2;
-
- /* set the destination */
- gimp_hsv_to_rgb_int (&r1, &g1, &b1);
-
- dest[0] = r1; dest[1] = g1; dest[2] = b1;
-
- if (has_alpha1 && has_alpha2)
- dest[3] = MIN (src1[3], src2[3]);
- else if (has_alpha2)
- dest[3] = src2[3];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
-}
-
-
-static inline void
-color_only_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
-
- /* assumes inputs are only 4 byte RGBA pixels */
- while (length--)
- {
- gint r1, g1, b1;
- gint r2, g2, b2;
-
- r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
- r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
-
- gimp_rgb_to_hsl_int (&r1, &g1, &b1);
- gimp_rgb_to_hsl_int (&r2, &g2, &b2);
-
- /* transfer hue and saturation to the source pixel */
- r1 = r2;
- g1 = g2;
-
- /* set the destination */
- gimp_hsl_to_rgb_int (&r1, &g1, &b1);
-
- dest[0] = r1; dest[1] = g1; dest[2] = b1;
-
- if (has_alpha1 && has_alpha2)
- dest[3] = MIN (src1[3], src2[3]);
- else if (has_alpha2)
- dest[3] = src2[3];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
-}
-
-
-static inline void
-multiply_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
- const guint alpha = ((has_alpha1 || has_alpha2) ?
- MAX (bytes1, bytes2) - 1 : bytes1);
-
- if (has_alpha1 && has_alpha2)
- {
- while (length --)
- {
- guint b;
-
- for (b = 0; b < alpha; b++)
- {
- guint tmp;
-
- dest[b] = INT_MULT(src1[b], src2[b], tmp);
- }
-
- dest[alpha] = MIN (src1[alpha], src2[alpha]);
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
- }
- else if (has_alpha2)
- {
- while (length --)
- {
- guint b;
-
- for (b = 0; b < alpha; b++)
- {
- guint tmp;
-
- dest[b] = INT_MULT(src1[b], src2[b], tmp);
- }
-
- dest[alpha] = src2[alpha];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
- }
- else
- {
- while (length --)
- {
- guint b;
-
- for (b = 0; b < alpha; b++)
- {
- guint tmp;
-
- dest[b] = INT_MULT (src1[b], src2[b], tmp);
- }
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
- }
-}
-
-
-static inline void
-divide_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
- const guint alpha = ((has_alpha1 || has_alpha2) ?
- MAX (bytes1, bytes2) - 1 : bytes1);
- while (length--)
- {
- guint b;
-
- for (b = 0; b < alpha; b++)
- {
- guint result = ((src1[b] * 256) / (1 + src2[b]));
-
- dest[b] = MIN (result, 255);
- }
-
- if (has_alpha1 && has_alpha2)
- dest[alpha] = MIN (src1[alpha], src2[alpha]);
- else if (has_alpha2)
- dest[alpha] = src2[alpha];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
-}
-
-
-static inline void
-screen_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
- const guint alpha = ((has_alpha1 || has_alpha2) ?
- MAX (bytes1, bytes2) - 1 : bytes1);
-
- while (length --)
- {
- guint b;
-
- for (b = 0; b < alpha; b++)
- {
- guint tmp;
-
- dest[b] = 255 - INT_MULT((255 - src1[b]), (255 - src2[b]), tmp);
- }
-
- if (has_alpha1 && has_alpha2)
- dest[alpha] = MIN (src1[alpha], src2[alpha]);
- else if (has_alpha2)
- dest[alpha] = src2[alpha];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
-}
-
-
-static inline void
-overlay_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
- const guint alpha = ((has_alpha1 || has_alpha2) ?
- MAX (bytes1, bytes2) - 1 : bytes1);
-
- while (length --)
- {
- guint b;
-
- for (b = 0; b < alpha; b++)
- {
- guint tmp, tmpM;
-
- dest[b] = INT_MULT(src1[b], src1[b] + INT_MULT (2 * src2[b],
- 255 - src1[b],
- tmpM), tmp);
- }
-
- if (has_alpha1 && has_alpha2)
- dest[alpha] = MIN (src1[alpha], src2[alpha]);
- else if (has_alpha2)
- dest[alpha] = src2[alpha];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
-}
-
-
-static inline void
-dodge_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
- const guint alpha = ((has_alpha1 || has_alpha2) ?
- MAX (bytes1, bytes2) - 1 : bytes1);
- while (length --)
- {
- guint b;
-
- for (b = 0; b < alpha; b++)
- {
- guint tmp;
-
- tmp = src1[b] << 8;
- tmp /= 256 - src2[b];
-
- dest[b] = (guchar) MIN (tmp, 255);
- }
-
- if (has_alpha1 && has_alpha2)
- dest[alpha] = MIN (src1[alpha], src2[alpha]);
- else if (has_alpha2)
- dest[alpha] = src2[alpha];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
-}
-
-
-static inline void
-burn_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
- const guint alpha = ((has_alpha1 || has_alpha2) ?
- MAX (bytes1, bytes2) - 1 : bytes1);
-
- while (length --)
- {
- guint b;
-
- for (b = 0; b < alpha; b++)
- {
- /* FIXME: Is the burn effect supposed to be dependant on the sign
- * of this temporary variable?
- */
- gint tmp;
-
- tmp = (255 - src1[b]) << 8;
- tmp /= src2[b] + 1;
-
- dest[b] = (guchar) CLAMP (255 - tmp, 0, 255);
- }
-
- if (has_alpha1 && has_alpha2)
- dest[alpha] = MIN (src1[alpha], src2[alpha]);
- else if (has_alpha2)
- dest[alpha] = src2[alpha];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
-}
-
-
-static inline void
-hardlight_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
- const guint alpha = ((has_alpha1 || has_alpha2) ?
- MAX (bytes1, bytes2) - 1 : bytes1);
-
- while (length --)
- {
- guint b;
-
- for (b = 0; b < alpha; b++)
- {
- guint tmp;
-
- if (src2[b] > 128)
- {
- tmp = (((gint)255 - src1[b]) *
- ((gint)255 - ((src2[b] - 128) << 1)));
- dest[b] = (guchar) MIN (255 - (tmp >> 8), 255);
- }
- else
- {
- tmp = (gint) src1[b] * ((gint)src2[b] << 1);
- dest[b] = (guchar) MIN (tmp >> 8, 255);
- }
- }
-
- if (has_alpha1 && has_alpha2)
- dest[alpha] = MIN (src1[alpha], src2[alpha]);
- else if (has_alpha2)
- dest[alpha] = src2[alpha];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
-}
-
-
-static inline void
-softlight_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
- const guint alpha = ((has_alpha1 || has_alpha2) ?
- MAX (bytes1, bytes2) - 1 : bytes1);
-
- while (length --)
- {
- guint b;
-
- for (b = 0; b < alpha; b++)
- {
- guint tmp1, tmp2, tmp3;
-
- /* Mix multiply and screen */
- guint tmpM = INT_MULT (src1[b], src2[b], tmpM);
- guint tmpS = 255 - INT_MULT((255 - src1[b]), (255 - src2[b]), tmp1);
-
- dest[b] = INT_MULT ((255 - src1[b]), tmpM, tmp2) +
- INT_MULT (src1[b], tmpS, tmp3);
- }
-
- if (has_alpha1 && has_alpha2)
- dest[alpha] = MIN (src1[alpha], src2[alpha]);
- else if (has_alpha2)
- dest[alpha] = src2[alpha];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
- }
-}
-
-
-static inline void
-grain_extract_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
- const guint alpha = ((has_alpha1 || has_alpha2) ?
- MAX (bytes1, bytes2) - 1 : bytes1);
-
- while (length --)
- {
- guint b;
+ guint b;
for (b = 0; b < alpha; b++)
+ dest[b] = p[b];
+
+ if (HAS_ALPHA (bytes))
{
- gint diff = src1[b] - src2[b] + 128;
+ if (mask)
+ dest[alpha] = *mask++;
+ else
+ dest[alpha] = OPAQUE_OPACITY;
- dest[b] = (guchar) CLAMP (diff, 0, 255);
+ if (HAS_ALPHA (pattern->bytes))
+ dest[alpha] = (guchar) (dest[alpha] *
+ p[alpha] / (gdouble) OPAQUE_OPACITY);
}
- if (has_alpha1 && has_alpha2)
- dest[alpha] = MIN (src1[alpha], src2[alpha]);
- else if (has_alpha2)
- dest[alpha] = src2[alpha];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
+ dest += bytes;
}
}
-
-static inline void
-grain_merge_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
+/*
+ * blend_pixels patched 8-24-05 to fix bug #163721. Note that this change
+ * causes the function to treat src1 and src2 asymmetrically. This gives the
+ * right behavior for the smudge tool, which is the only user of this function
+ * at the time of patching. If you want to use the function for something
+ * else, caveat emptor.
+ */
+inline void
+blend_pixels (const guchar *src1,
+ const guchar *src2,
+ guchar *dest,
+ guchar blend,
+ guint w,
+ guint bytes)
{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
- const guint alpha = ((has_alpha1 || has_alpha2) ?
- MAX (bytes1, bytes2) - 1 : bytes1);
-
- while (length --)
+ if (HAS_ALPHA (bytes))
{
- guint b;
+ const guint blend1 = 255 - blend;
+ const guint blend2 = blend + 1;
+ const guint c = bytes - 1;
- for (b = 0; b < alpha; b++)
+ while (w--)
{
- /* Add, re-center and clip. */
- gint sum = src1[b] + src2[b] - 128;
+ const gint a1 = blend1 * src1[c];
+ const gint a2 = blend2 * src2[c];
+ const gint a = a1 + a2;
+ guint b;
- dest[b] = (guchar) CLAMP (sum, 0, 255);
- }
+ if (!a)
+ {
+ for (b = 0; b < bytes; b++)
+ dest[b] = 0;
+ }
+ else
+ {
+ for (b = 0; b < c; b++)
+ dest[b] =
+ src1[b] + (src1[b] * a1 + src2[b] * a2 - a * src1[b]) / a;
- if (has_alpha1 && has_alpha2)
- dest[alpha] = MIN (src1[alpha], src2[alpha]);
- else if (has_alpha2)
- dest[alpha] = src2[alpha];
+ dest[c] = a >> 8;
+ }
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
+ src1 += bytes;
+ src2 += bytes;
+ dest += bytes;
+ }
}
-}
-
-
-static inline void
-add_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
- const guint alpha = ((has_alpha1 || has_alpha2) ?
- MAX (bytes1, bytes2) - 1 : bytes1);
-
- while (length --)
+ else
{
- guint b;
+ const guchar blend1 = 255 - blend;
- for (b = 0; b < alpha; b++)
- dest[b] = add_lut[src1[b] + src2[b]];
+ while (w--)
+ {
+ guint b;
- if (has_alpha1 && has_alpha2)
- dest[alpha] = MIN (src1[alpha], src2[alpha]);
- else if (has_alpha2)
- dest[alpha] = src2[alpha];
+ for (b = 0; b < bytes; b++)
+ dest[b] =
+ src1[b] + (src1[b] * blend1 + src2[b] * blend - src1[b] * 255) / 255;
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
+ src1 += bytes;
+ src2 += bytes;
+ dest += bytes;
+ }
}
}
+inline void
+shade_pixels (const guchar *src,
+ guchar *dest,
+ const guchar *col,
+ guchar blend,
+ guint w,
+ guint bytes,
+ gboolean has_alpha)
+{
+ const guchar blend2 = (255 - blend);
+ const guint alpha = (has_alpha) ? bytes - 1 : bytes;
-static inline void
-subtract_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
-{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
- const guint alpha = ((has_alpha1 || has_alpha2) ?
- MAX (bytes1, bytes2) - 1 : bytes1);
-
- while (length --)
+ while (w--)
{
guint b;
for (b = 0; b < alpha; b++)
- {
- gint diff = src1[b] - src2[b];
-
- dest[b] = (diff < 0) ? 0 : diff;
- }
+ dest[b] = (src[b] * blend2 + col[b] * blend) / 255;
- if (has_alpha1 && has_alpha2)
- dest[alpha] = MIN (src1[alpha], src2[alpha]);
- else if (has_alpha2)
- dest[alpha] = src2[alpha];
+ if (has_alpha)
+ dest[alpha] = src[alpha]; /* alpha channel */
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
+ src += bytes;
+ dest += bytes;
}
}
-static inline void
-difference_pixels (const guchar *src1,
- const guchar *src2,
- guchar *dest,
- guint length,
- guint bytes1,
- guint bytes2)
+inline void
+extract_alpha_pixels (const guchar *src,
+ const guchar *mask,
+ guchar *dest,
+ guint w,
+ guint bytes)
{
- const guint has_alpha1 = HAS_ALPHA (bytes1);
- const guint has_alpha2 = HAS_ALPHA (bytes2);
- const guint alpha = ((has_alpha1 || has_alpha2) ?
- MAX (bytes1, bytes2) - 1 : bytes1);
+ const guint alpha = bytes - 1;
- while (length --)
+ if (mask)
{
- guint b;
+ const guchar *m = mask;
- for (b = 0; b < alpha; b++)
+ while (w--)
{
- gint diff = src1[b] - src2[b];
+ gint tmp;
- dest[b] = (diff < 0) ? -diff : diff;
+ *dest++ = INT_MULT(src[alpha], *m, tmp);
+ m++;
+ src += bytes;
}
-
- if (has_alpha1 && has_alpha2)
- dest[alpha] = MIN (src1[alpha], src2[alpha]);
- else if (has_alpha2)
- dest[alpha] = src2[alpha];
-
- src1 += bytes1;
- src2 += bytes2;
- dest += bytes2;
}
-}
-
-
-static inline void
-dissolve_pixels (const guchar *src,
- const guchar *mask,
- guchar *dest,
- gint x,
- gint y,
- gint opacity,
- gint length,
- gint sb,
- gint db,
- gboolean has_alpha)
-{
- const gint alpha = db - 1;
- gint b;
- GRand *gr;
-
- gr = g_rand_new_with_seed (random_table[y % RANDOM_TABLE_SIZE]);
-
- /* Ignore x random values so we get a deterministic result */
- for (b = 0; b < x; b ++)
- g_rand_int (gr);
-
- while (length--)
+ else
{
- gint combined_opacity;
- gint32 rand_val;
-
- /* preserve the intensity values */
- for (b = 0; b < alpha; b++)
- dest[b] = src[b];
-
- /* dissolve if random value is >= opacity */
- rand_val = g_rand_int_range (gr, 0, 255);
-
- if (mask)
+ while (w--)
{
- if (has_alpha)
- combined_opacity = opacity * src[alpha] * *mask / (255 * 255);
- else
- combined_opacity = opacity * *mask / 255;
+ gint tmp;
- mask++;
- }
- else
- {
- if (has_alpha)
- combined_opacity = opacity * src[alpha] / 255;
- else
- combined_opacity = opacity;
+ *dest++ = INT_MULT(src[alpha], OPAQUE_OPACITY, tmp);
+ src += bytes;
}
-
- dest[alpha] = (rand_val >= combined_opacity) ? 0 : OPAQUE_OPACITY;
-
- src += sb;
- dest += db;
}
-
- g_rand_free (gr);
-
}
+
static inline void
replace_pixels (const guchar *src1,
const guchar *src2,
@@ -1882,226 +1007,4 @@
}
-static void
-layer_normal_mode (struct apply_layer_mode_struct *alms)
-{
- /* assumes we're applying src2 TO src1 */
- *(alms->dest) = alms->src2;
-}
-
-static void
-layer_dissolve_mode (struct apply_layer_mode_struct *alms)
-{
- const guint has_alpha1 = HAS_ALPHA (alms->bytes1);
- const guint has_alpha2 = HAS_ALPHA (alms->bytes2);
- guint dest_bytes;
-
- /* Since dissolve requires an alpha channel... */
- if (has_alpha2)
- dest_bytes = alms->bytes2;
- else
- dest_bytes = alms->bytes2 + 1;
-
- dissolve_pixels (alms->src2, alms->mask, *(alms->dest),
- alms->x, alms->y,
- alms->opacity, alms->length,
- alms->bytes2, dest_bytes,
- has_alpha2);
-
- alms->combine = has_alpha1 ? COMBINE_INTEN_A_INTEN_A : COMBINE_INTEN_INTEN_A;
-}
-
-static void
-layer_multiply_mode (struct apply_layer_mode_struct *alms)
-{
- multiply_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_divide_mode (struct apply_layer_mode_struct *alms)
-{
- divide_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_screen_mode (struct apply_layer_mode_struct *alms)
-{
- screen_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_overlay_mode (struct apply_layer_mode_struct *alms)
-{
- overlay_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_difference_mode (struct apply_layer_mode_struct *alms)
-{
- difference_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_addition_mode (struct apply_layer_mode_struct *alms)
-{
- add_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_subtract_mode (struct apply_layer_mode_struct *alms)
-{
- subtract_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_darken_only_mode (struct apply_layer_mode_struct *alms)
-{
- darken_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_lighten_only_mode (struct apply_layer_mode_struct *alms)
-{
- lighten_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_hue_mode (struct apply_layer_mode_struct *alms)
-{
- /* only works on RGB color images */
- if (alms->bytes1 > 2)
- hue_only_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
- else
- *(alms->dest) = alms->src2;
-}
-
-static void
-layer_saturation_mode (struct apply_layer_mode_struct *alms)
-{
- /* only works on RGB color images */
- if (alms->bytes1 > 2)
- saturation_only_pixels (alms->src1, alms->src2, *(alms->dest),
- alms->length, alms->bytes1, alms->bytes2);
- else
- *(alms->dest) = alms->src2;
-}
-
-static void
-layer_value_mode (struct apply_layer_mode_struct *alms)
-{
- /* only works on RGB color images */
- if (alms->bytes1 > 2)
- value_only_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
- else
- *(alms->dest) = alms->src2;
-}
-
-static void
-layer_color_mode (struct apply_layer_mode_struct *alms)
-{
- /* only works on RGB color images */
- if (alms->bytes1 > 2)
- color_only_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
- else
- *(alms->dest) = alms->src2;
-}
-
-static void
-layer_behind_mode (struct apply_layer_mode_struct *alms)
-{
- *(alms->dest) = alms->src2;
- if (HAS_ALPHA (alms->bytes1))
- alms->combine = BEHIND_INTEN;
- else
- alms->combine = NO_COMBINATION;
-}
-
-static void
-layer_replace_mode (struct apply_layer_mode_struct *alms)
-{
- *(alms->dest) = alms->src2;
- alms->combine = REPLACE_INTEN;
-}
-
-static void
-layer_erase_mode (struct apply_layer_mode_struct *alms)
-{
- *(alms->dest) = alms->src2;
- /* If both sources have alpha channels, call erase function.
- * Otherwise, just combine in the normal manner
- */
- alms->combine =
- (HAS_ALPHA (alms->bytes1) && HAS_ALPHA (alms->bytes2)) ? ERASE_INTEN : 0;
-}
-
-static void
-layer_anti_erase_mode (struct apply_layer_mode_struct *alms)
-{
- *(alms->dest) = alms->src2;
- alms->combine =
- (HAS_ALPHA (alms->bytes1) && HAS_ALPHA (alms->bytes2)) ? ANTI_ERASE_INTEN : 0;
-}
-
-static void
-layer_color_erase_mode (struct apply_layer_mode_struct *alms)
-{
- *(alms->dest) = alms->src2;
- alms->combine =
- (HAS_ALPHA (alms->bytes1) && HAS_ALPHA (alms->bytes2)) ? COLOR_ERASE_INTEN : 0;
-}
-
-static void
-layer_dodge_mode (struct apply_layer_mode_struct *alms)
-{
- dodge_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_burn_mode (struct apply_layer_mode_struct *alms)
-{
- burn_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_hardlight_mode (struct apply_layer_mode_struct *alms)
-{
- hardlight_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_softlight_mode (struct apply_layer_mode_struct *alms)
-{
- softlight_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_grain_extract_mode (struct apply_layer_mode_struct *alms)
-{
- grain_extract_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_grain_merge_mode (struct apply_layer_mode_struct *alms)
-{
- grain_merge_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
- alms->bytes1, alms->bytes2);
-}
-
#endif /* __PAINT_FUNCS_GENERIC_H__ */
Added: trunk/app/paint-funcs/paint-funcs-utils.h
==============================================================================
--- (empty file)
+++ trunk/app/paint-funcs/paint-funcs-utils.h Mon Oct 13 18:51:32 2008
@@ -0,0 +1,46 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PAINT_FUNCS_UTILS_H__
+#define __PAINT_FUNCS_UTILS_H__
+
+
+#define INT_MULT(a,b,t) ((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8))
+
+/* This version of INT_MULT3 is very fast, but suffers from some
+ slight roundoff errors. It returns the correct result 99.987
+ percent of the time */
+#define INT_MULT3(a,b,c,t) ((t) = (a) * (b) * (c) + 0x7F5B, \
+ ((((t) >> 7) + (t)) >> 16))
+/*
+ This version of INT_MULT3 always gives the correct result, but runs at
+ approximatly one third the speed. */
+/* #define INT_MULT3(a,b,c,t) (((a) * (b) * (c) + 32512) / 65025.0)
+ */
+
+#define INT_BLEND(a,b,alpha,tmp) (INT_MULT((a) - (b), alpha, tmp) + (b))
+
+/* A drawable has an alphachannel if contains either 4 or 2 bytes data
+ * aka GRAYA and RGBA and thus the macro below works. This will have
+ * to change if we support bigger formats. We'll do it so for now because
+ * masking is always cheaper than passing parameters over the stack. */
+/* FIXME: Move to a global place */
+#define HAS_ALPHA(bytes) (~bytes & 1)
+
+
+#endif /* __PAINT_FUNCS_UTILS_H__ */
Modified: trunk/app/paint-funcs/paint-funcs.c
==============================================================================
--- trunk/app/paint-funcs/paint-funcs.c (original)
+++ trunk/app/paint-funcs/paint-funcs.c Mon Oct 13 18:51:32 2008
@@ -37,10 +37,11 @@
#include "composite/gimp-composite.h"
#include "paint-funcs.h"
+#include "layer-modes.h"
+#include "paint-funcs-utils.h"
#include "paint-funcs-generic.h"
-#define RANDOM_SEED 314159265
#define EPSILON 0.0001
#define LOG_1_255 -5.541263545 /* log (1.0 / 255.0) */
@@ -248,22 +249,7 @@
void
paint_funcs_setup (void)
{
- GRand *gr;
- gint i;
-
- /* generate a table of random seeds */
- gr = g_rand_new_with_seed (RANDOM_SEED);
-
- for (i = 0; i < RANDOM_TABLE_SIZE; i++)
- random_table[i] = g_rand_int (gr);
-
- for (i = 0; i < 256; i++)
- add_lut[i] = i;
-
- for (i = 256; i <= 510; i++)
- add_lut[i] = 255;
-
- g_rand_free (gr);
+ layer_modes_setup ();
}
void
@@ -668,40 +654,6 @@
}
}
-/*orig #define alphify(src2_alpha,new_alpha) \
- if (new_alpha == 0 || src2_alpha == 0) \
- { \
- for (b = 0; b < alpha; b++) \
- dest[b] = src1 [b]; \
- } \
- else if (src2_alpha == new_alpha){ \
- for (b = 0; b < alpha; b++) \
- dest [b] = affect [b] ? src2 [b] : src1 [b]; \
- } else { \
- ratio = (float) src2_alpha / new_alpha; \
- compl_ratio = 1.0 - ratio; \
- \
- for (b = 0; b < alpha; b++) \
- dest[b] = affect[b] ? \
- (guchar) (src2[b] * ratio + src1[b] * compl_ratio + EPSILON) : src1[b]; \
- }*/
-
-/*shortened #define alphify(src2_alpha,new_alpha) \
- if (src2_alpha != 0 && new_alpha != 0) \
- { \
- if (src2_alpha == new_alpha){ \
- for (b = 0; b < alpha; b++) \
- dest [b] = affect [b] ? src2 [b] : src1 [b]; \
- } else { \
- ratio = (float) src2_alpha / new_alpha; \
- compl_ratio = 1.0 - ratio; \
- \
- for (b = 0; b < alpha; b++) \
- dest[b] = affect[b] ? \
- (guchar) (src2[b] * ratio + src1[b] * compl_ratio + EPSILON) : src1[b];\
- } \
- }*/
-
#define alphify(src2_alpha,new_alpha) \
if (src2_alpha != 0 && new_alpha != 0) \
{ \
@@ -720,26 +672,6 @@
} \
}
-/*special #define alphify4(src2_alpha,new_alpha) \
- if (src2_alpha != 0 && new_alpha != 0) \
- { \
- if (src2_alpha == new_alpha){ \
- dest [0] = affect [0] ? src2 [0] : src1 [0]; \
- dest [1] = affect [1] ? src2 [1] : src1 [1]; \
- dest [2] = affect [2] ? src2 [2] : src1 [2]; \
- } else { \
- ratio = (float) src2_alpha / new_alpha; \
- compl_ratio = 1.0 - ratio; \
- \
- dest[0] = affect[0] ? \
- (guchar) (src2[0] * ratio + src1[0] * compl_ratio + EPSILON) : src1[0]; \
- dest[1] = affect[1] ? \
- (guchar) (src2[1] * ratio + src1[1] * compl_ratio + EPSILON) : src1[1]; \
- dest[2] = affect[2] ? \
- (guchar) (src2[2] * ratio + src1[2] * compl_ratio + EPSILON) : src1[2]; \
- } \
- }*/
-
void
combine_inten_a_and_inten_pixels (const guchar *src1,
const guchar *src2,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]