[gegl] gegl:invert[-gamma]: add format-specific variants
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] gegl:invert[-gamma]: add format-specific variants
- Date: Thu, 3 Jan 2019 10:00:17 +0000 (UTC)
commit fee15ff5dda2e8898937dbb03b70bc4437c6bd10
Author: Ell <ell_se yahoo com>
Date: Thu Jan 3 04:54:42 2019 -0500
gegl:invert[-gamma]: add format-specific variants
Factor out the common logic of gegl:invert and gegl:invert-gamma
into invert-common.h, and implement format-specific variants, which
significantly improves performance for int images. In particular,
this speeds up selection invertion in GIMP, which uses gegl:invert.
operations/common/Makefile.am | 1 +
operations/common/invert-common.h | 267 ++++++++++++++++++++++++++++++++++++++
operations/common/invert-gamma.c | 33 +----
operations/common/invert-linear.c | 26 +---
4 files changed, 273 insertions(+), 54 deletions(-)
---
diff --git a/operations/common/Makefile.am b/operations/common/Makefile.am
index 86426de71..924ceca24 100644
--- a/operations/common/Makefile.am
+++ b/operations/common/Makefile.am
@@ -56,6 +56,7 @@ gegl_common_la_SOURCES =\
image-compare.c \
image-gradient.c \
introspect.c \
+ invert-common.h \
invert-gamma.c \
invert-linear.c \
layer.c \
diff --git a/operations/common/invert-common.h b/operations/common/invert-common.h
new file mode 100644
index 000000000..9d01cc05b
--- /dev/null
+++ b/operations/common/invert-common.h
@@ -0,0 +1,267 @@
+#ifndef PROCESS_MODEL_SUFFIX
+
+#define INVERT_CAT(x, y) INVERT_CAT_I (x, y)
+#define INVERT_CAT_I(x, y) x ## y
+
+typedef gboolean (* ProcessFunc) (GeglOperation *op,
+ void *in_buf,
+ void *out_buf,
+ glong samples,
+ const GeglRectangle *roi,
+ gint level);
+
+#define PROCESS_FUNC(model_suffix, type_suffix) \
+ INVERT_CAT (process_, INVERT_CAT (model_suffix, INVERT_CAT (_, type_suffix)))
+
+static gboolean
+process_int (ProcessFunc func,
+ guint32 mask,
+ GeglOperation *op,
+ void *in_buf,
+ void *out_buf,
+ glong samples,
+ const GeglRectangle *roi,
+ gint level)
+{
+ const guint8 *in = in_buf;
+ guint8 *out = out_buf;
+ const guint32 *in32;
+ guint32 *out32;
+
+ if (((guintptr) in - (guintptr) out) % 4 ||
+ (G_BYTE_ORDER != G_LITTLE_ENDIAN && ~mask))
+ {
+ return func (op, in_buf, out_buf, samples, roi, level);
+ }
+
+ while (samples && (guintptr) in % 4)
+ {
+ *out++ = *in++ ^ (guint8) mask;
+
+ mask = (mask >> 8) | (mask << 24);
+
+ samples--;
+ }
+
+ in32 = (const guint32 *) in;
+ out32 = (guint32 *) out;
+
+ while (samples >= 4)
+ {
+ *out32++ = *in32++ ^ mask;
+
+ samples -= 4;
+ }
+
+ in = (const guint8 *) in32;
+ out = (guint8 *) out32;
+
+ while (samples)
+ {
+ *out++ = *in++ ^ (guint8) mask;
+
+ mask >>= 8;
+
+ samples--;
+ }
+
+ return TRUE;
+}
+
+#define PROCESS_MODEL_SUFFIX y
+#define PROCESS_N_COMPONENTS 1
+#define PROCESS_HAS_ALPHA FALSE
+#include "invert-common.h"
+
+#define PROCESS_MODEL_SUFFIX ya
+#define PROCESS_N_COMPONENTS 1
+#define PROCESS_HAS_ALPHA TRUE
+#include "invert-common.h"
+
+#define PROCESS_MODEL_SUFFIX rgb
+#define PROCESS_N_COMPONENTS 3
+#define PROCESS_HAS_ALPHA FALSE
+#include "invert-common.h"
+
+#define PROCESS_MODEL_SUFFIX rgba
+#define PROCESS_N_COMPONENTS 3
+#define PROCESS_HAS_ALPHA TRUE
+#include "invert-common.h"
+
+static void
+prepare (GeglOperation *operation)
+{
+ GeglProperties *o = GEGL_PROPERTIES (operation);
+ const Babl *in_format = gegl_operation_get_source_format (operation,
+ "input");
+ const Babl *format = NULL;
+
+ if (in_format)
+ {
+ const Babl *model = babl_format_get_model (in_format);
+ const Babl *type = babl_format_get_type (in_format, 0);
+
+ #define DISPATCH_TYPE(model_suffix, type_name, type_suffix) \
+ if (type == babl_type (type_name)) \
+ { \
+ o->user_data = PROCESS_FUNC (model_suffix, type_suffix); \
+ \
+ format = in_format; \
+ }
+
+ #define DISPATCH_MODEL(model_name, model_suffix) \
+ if (babl_model_is (model, model_name)) \
+ { \
+ DISPATCH_TYPE (model_suffix, "u8", u8) \
+ else DISPATCH_TYPE (model_suffix, "u16", u16) \
+ else DISPATCH_TYPE (model_suffix, "u32", u32) \
+ else DISPATCH_TYPE (model_suffix, "float", float) \
+ }
+
+ DISPATCH_MODEL ("Y" INVERT_GAMMA,
+ y)
+ else DISPATCH_MODEL ("Y" INVERT_GAMMA
+ "A",
+ ya)
+ else DISPATCH_MODEL ("R" INVERT_GAMMA
+ "G" INVERT_GAMMA
+ "B" INVERT_GAMMA,
+ rgb)
+ else DISPATCH_MODEL ("R" INVERT_GAMMA
+ "G" INVERT_GAMMA
+ "B" INVERT_GAMMA
+ "A",
+ rgba)
+
+ #undef DISPATCH_TYPE
+ #undef DISPATCH_MODEL
+ }
+
+ if (! format)
+ {
+ o->user_data = PROCESS_FUNC (rgba, float);
+
+ if (in_format)
+ {
+ format = babl_format_with_space ("R" INVERT_GAMMA
+ "G" INVERT_GAMMA
+ "B" INVERT_GAMMA
+ "A"
+ " float",
+ in_format);
+ }
+ else
+ {
+ format = babl_format ("R" INVERT_GAMMA
+ "G" INVERT_GAMMA
+ "B" INVERT_GAMMA
+ "A"
+ " float");
+ }
+ }
+
+ gegl_operation_set_format (operation, "input", format);
+ gegl_operation_set_format (operation, "output", format);
+}
+
+static gboolean
+process (GeglOperation *op,
+ void *in_buf,
+ void *out_buf,
+ glong samples,
+ const GeglRectangle *roi,
+ gint level)
+{
+ GeglProperties *o = GEGL_PROPERTIES (op);
+ ProcessFunc func = o->user_data;
+
+ return func (op, in_buf, out_buf, samples, roi, level);
+}
+
+#else /* defined (PROCESS_MODEL_SUFFIX) */
+
+#ifndef PROCESS_TYPE_SUFFIX
+
+#define PROCESS_TYPE_SUFFIX u8_
+#define PROCESS_TYPE guint8
+#define PROCESS_INVERT(x) (~(x))
+#include "invert-common.h"
+
+static gboolean
+PROCESS_FUNC (PROCESS_MODEL_SUFFIX, u8) (GeglOperation *op,
+ void *in_buf,
+ void *out_buf,
+ glong samples,
+ const GeglRectangle *roi,
+ gint level)
+{
+ return process_int (PROCESS_FUNC (PROCESS_MODEL_SUFFIX, u8_),
+ #if ! PROCESS_HAS_ALPHA
+ 0xffffffff,
+ #elif PROCESS_N_COMPONENTS == 1
+ 0x00ff00ff,
+ #elif PROCESS_N_COMPONENTS == 3
+ 0x00ffffff,
+ #endif
+ op, in_buf, out_buf,
+ (PROCESS_N_COMPONENTS + PROCESS_HAS_ALPHA) * samples,
+ roi, level);
+}
+
+#define PROCESS_TYPE_SUFFIX u16
+#define PROCESS_TYPE guint16
+#define PROCESS_INVERT(x) (~(x))
+#include "invert-common.h"
+
+#define PROCESS_TYPE_SUFFIX u32
+#define PROCESS_TYPE guint32
+#define PROCESS_INVERT(x) (~(x))
+#include "invert-common.h"
+
+#define PROCESS_TYPE_SUFFIX float
+#define PROCESS_TYPE gfloat
+#define PROCESS_INVERT(x) (1.0f - (x))
+#include "invert-common.h"
+
+#undef PROCESS_MODEL_SUFFIX
+#undef PROCESS_N_COMPONENTS
+#undef PROCESS_HAS_ALPHA
+
+#else /* defined (PROCESS_TYPE_SUFFIX) */
+
+static gboolean
+PROCESS_FUNC (PROCESS_MODEL_SUFFIX, PROCESS_TYPE_SUFFIX) (GeglOperation *op,
+ void *in_buf,
+ void *out_buf,
+ glong samples,
+ const GeglRectangle *roi,
+ gint level)
+{
+ const PROCESS_TYPE *in = in_buf;
+ PROCESS_TYPE *out = out_buf;
+
+ while (samples--)
+ {
+ gint i;
+
+ for (i = 0; i < PROCESS_N_COMPONENTS; i++)
+ out[i] = PROCESS_INVERT (in[i]);
+
+ #if PROCESS_HAS_ALPHA
+ out[PROCESS_N_COMPONENTS] = in[PROCESS_N_COMPONENTS];
+ #endif
+
+ in += PROCESS_N_COMPONENTS + PROCESS_HAS_ALPHA;
+ out += PROCESS_N_COMPONENTS + PROCESS_HAS_ALPHA;
+ }
+
+ return TRUE;
+}
+
+#undef PROCESS_TYPE_SUFFIX
+#undef PROCESS_TYPE
+#undef PROCESS_INVERT
+
+#endif /* defined (PROCESS_TYPE_SUFFIX) */
+
+#endif /* defined (PROCESS_MODEL_SUFFIX) */
diff --git a/operations/common/invert-gamma.c b/operations/common/invert-gamma.c
index a0b6e14c3..bf25c5aa3 100644
--- a/operations/common/invert-gamma.c
+++ b/operations/common/invert-gamma.c
@@ -32,37 +32,8 @@
#include "gegl-op.h"
-static void
-prepare (GeglOperation *operation)
-{
- const Babl *space = gegl_operation_get_source_space (operation, "input");
- gegl_operation_set_format (operation, "input", babl_format_with_space ("R'G'B'A float", space));
- gegl_operation_set_format (operation, "output", babl_format_with_space ("R'G'B'A float", space));
-}
-
-static gboolean
-process (GeglOperation *op,
- void *in_buf,
- void *out_buf,
- glong samples,
- const GeglRectangle *roi,
- gint level)
-{
- gfloat *in = in_buf;
- gfloat *out = out_buf;
-
- while (samples--)
- {
- out[0] = 1.0 - in[0];
- out[1] = 1.0 - in[1];
- out[2] = 1.0 - in[2];
- out[3] = in[3];
-
- in += 4;
- out+= 4;
- }
- return TRUE;
-}
+#define INVERT_GAMMA "'"
+#include "invert-common.h"
static void
gegl_op_class_init (GeglOpClass *klass)
diff --git a/operations/common/invert-linear.c b/operations/common/invert-linear.c
index b1d497bd9..f751a3037 100644
--- a/operations/common/invert-linear.c
+++ b/operations/common/invert-linear.c
@@ -32,29 +32,8 @@
#include "gegl-op.h"
-static gboolean
-process (GeglOperation *op,
- void *in_buf,
- void *out_buf,
- glong samples,
- const GeglRectangle *roi,
- gint level)
-{
- gfloat *in = in_buf;
- gfloat *out = out_buf;
-
- while (samples--)
- {
- out[0] = 1.0 - in[0];
- out[1] = 1.0 - in[1];
- out[2] = 1.0 - in[2];
- out[3] = in[3];
-
- in += 4;
- out+= 4;
- }
- return TRUE;
-}
+#define INVERT_GAMMA ""
+#include "invert-common.h"
#include "opencl/invert-linear.cl.h"
@@ -67,6 +46,7 @@ gegl_op_class_init (GeglOpClass *klass)
operation_class = GEGL_OPERATION_CLASS (klass);
point_filter_class = GEGL_OPERATION_POINT_FILTER_CLASS (klass);
+ operation_class->prepare = prepare;
point_filter_class->process = process;
gegl_operation_class_set_keys (operation_class,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]