[Cin] new overlay mode from Freelancer

Andrew Randrianasulu randrianasulu at gmail.com
Wed Jun 30 01:05:07 CEST 2021


tried to add faster srgb to/from linear from this source

https://stackoverflow.com/questions/6475373/optimizations-for-pow-with-const-non-integer-exponent

see answer with poly7 code.

still around 8-9 fps on full HD frames (png), while different composition
mode (porter/duff, srcOnTop) does 22 fps!

On Tuesday, June 29, 2021, Andrew Randrianasulu <randrianasulu at gmail.com>
wrote:

> updated diff attached, now both 'my' new modes (avg was around before but
> was deleted at some point.. <*>) works in plain x11. probably for opengl
> preview you need to a bit more lines..
>
> reason why it failed to compile at first - one (!) additional space in
> defines for new mode..
>
> <*> http://git.cinelerra-gg.org/git/?p=goodguy/history.git;a=commit;h=
> 93d60cc0fdf746cc03b4d7a9e45744c2c424439b
>
>
>
> On Tuesday, June 29, 2021, Andrew Randrianasulu <randrianasulu at gmail.com>
> wrote:
>
>> finally looked at history..
>>
>> http://git.cinelerra-gg.org/git/?p=goodguy/history.git;a=blo
>> bdiff;f=cinelerra-5.1/cinelerra/overlayframe.h;h=730be3741ed
>> 638b54703c530809aeaada999e20e;hp=7ca03621e6b6df0b91b165e9566
>> fbc263a2074b0;hb=93d60cc0fdf746cc03b4d7a9e45744c2c424439b;
>> hpb=361dbd9de4e6e4143ea0cac5daa89b30685a4c70
>>
>> and made this patch (attached)
>>
>> it works softer than logical or porter/duff modes, but notiecably  slower
>> ( (on 8 core arm tablet)
>>
>>
>> my modes fails to compile - something about me not really knowing how to
>> write macro functions (?)
>>
>>
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.cinelerra-gg.org/pipermail/cin/attachments/20210630/71ea1dce/attachment-0001.htm>
-------------- next part --------------
inline double poly7(double x, double a, double b, double c, double d,
                              double e, double f, double g, double h) {
    double ab, cd, ef, gh, abcd, efgh, x2, x4;
    x2 = x*x; x4 = x2*x2;
    ab = a*x + b; cd = c*x + d;
    ef = e*x + f; gh = g*x + h;
    abcd = ab*x2 + cd; efgh = ef*x2 + gh;
    return abcd*x4 + efgh;
}

inline double srgb_to_linear(double x) {
    if (x <= 0.04045) return x / 12.92;

    // Polynomial approximation of ((x+0.055)/1.055)^2.4.
    return poly7(x, 0.15237971711927983387,
                   -0.57235993072870072762,
                    0.92097986411523535821,
                   -0.90208229831912012386,
                    0.88348956209696805075,
                    0.48110797889132134175,
                    0.03563925285274562038,
                    0.00084585397227064120);
}

inline double linear_to_srgb(double x) {
    if (x <= 0.0031308) return x * 12.92;

    // Piecewise polynomial approximation (divided by x^3)
    // of 1.055 * x^(1/2.4) - 0.055.
    if (x <= 0.0523) return poly7(x, -6681.49576364495442248881,
                                      1224.97114922729451791383,
                                      -100.23413743425112443219,
                                         6.60361150127077944916,
                                         0.06114808961060447245,
                                        -0.00022244138470139442,
                                         0.00000041231840827815,
                                        -0.00000000035133685895) / (x*x*x);

    return poly7(x, -0.18730034115395793881,
                     0.64677431008037400417,
                    -0.99032868647877825286,
                     1.20939072663263713636,
                     0.33433459165487383613,
                    -0.01345095746411287783,
                     0.00044351684288719036,
                    -0.00000664263587520855) / (x*x*x);
}

// from https://stackoverflow.com/questions/6475373/optimizations-for-pow-with-const-non-integer-exponent

-------------- next part --------------
diff --git a/cinelerra-5.1/cinelerra/overlayframe.C b/cinelerra-5.1/cinelerra/overlayframe.C
index 270755cc..801ae9d3 100644
--- a/cinelerra-5.1/cinelerra/overlayframe.C
+++ b/cinelerra-5.1/cinelerra/overlayframe.C
@@ -351,5 +351,3 @@ int OverlayFrame::overlay(VFrame *output, VFrame *input,
 	}
 	return 0;
 }
-
-
diff --git a/cinelerra-5.1/cinelerra/overlayframe.h b/cinelerra-5.1/cinelerra/overlayframe.h
index 13c2e4bd..ace2fa02 100644
--- a/cinelerra-5.1/cinelerra/overlayframe.h
+++ b/cinelerra-5.1/cinelerra/overlayframe.h
@@ -45,6 +45,9 @@
 #define ONE 1
 #define TWO 2
 
+// Sa = source alpha, Sc = source color
+// Da = dst alpha, Dc = dst color
+
 // NORMAL	[Sa + Da * (1 - Sa), Sc * Sa + Dc * (1 - Sa)])
 #define ALPHA_NORMAL(mx, Sa, Da) (Sa + (Da * (mx - Sa)) / mx)
 #define COLOR_NORMAL(mx, Sc, Sa, Dc, Da) ((Sc * Sa + Dc * (mx - Sa)) / mx)
@@ -220,6 +223,86 @@
   (mabs(Sc * Da - Dc * Sa) / mx))
 #define CHROMA_DIFFERENCE COLOR_DIFFERENCE
 
+// REFLECT [Sa * Sa / (1 - Da]
+#define ALPHA_REFLECT(mx, Sa, Da) (Sa * Sa  * (mx - Da) / mx)
+#define COLOR_REFLECT(mx, Sc, Sa, Dc, Da) (Sc * Sc * (mx - Dc) / mx)
+#define CHROMA_REFLECT COLOR_REFLECT
+
+// AVERAGE [ Sa + Da)/2 , (Sc + Dc)/2 ]
+#define ALPHA_AVERAGE(mx, Sa, Da) ((Sa + Da) / 2)
+#define COLOR_AVERAGE(mx, Sc, Sa,  Dc, Da) ((Sc + Dc) / 2 )
+#define CHROMA_AVERAGE COLOR_AVERAGE
+
+#define GAMMA 2.4
+static inline double mpow(double a, double b) { return pow(a, b); }
+
+inline double poly7(double x, double a, double b, double c, double d,
+                              double e, double f, double g, double h) {
+    double ab, cd, ef, gh, abcd, efgh, x2, x4;
+    x2 = x*x; x4 = x2*x2;
+    ab = a*x + b; cd = c*x + d;
+    ef = e*x + f; gh = g*x + h;
+    abcd = ab*x2 + cd; efgh = ef*x2 + gh;
+    return abcd*x4 + efgh;
+}
+
+inline double srgb_to_linear(double x) {
+    if (x <= 0.04045) return x / 12.92;
+
+    // Polynomial approximation of ((x+0.055)/1.055)^2.4.
+    return poly7(x, 0.15237971711927983387,
+                   -0.57235993072870072762,
+                    0.92097986411523535821,
+                   -0.90208229831912012386,
+                    0.88348956209696805075,
+                    0.48110797889132134175,
+                    0.03563925285274562038,
+                    0.00084585397227064120);
+}
+
+inline double linear_to_srgb(double x) {
+    if (x <= 0.0031308) return x * 12.92;
+
+    // Piecewise polynomial approximation (divided by x^3)
+    // of 1.055 * x^(1/2.4) - 0.055.
+    if (x <= 0.0523) return poly7(x, -6681.49576364495442248881,
+                                      1224.97114922729451791383,
+                                      -100.23413743425112443219,
+                                         6.60361150127077944916,
+                                         0.06114808961060447245,
+                                        -0.00022244138470139442,
+                                         0.00000041231840827815,
+                                        -0.00000000035133685895) / (x*x*x);
+
+    return poly7(x, -0.18730034115395793881,
+                     0.64677431008037400417,
+                    -0.99032868647877825286,
+                     1.20939072663263713636,
+                     0.33433459165487383613,
+                    -0.01345095746411287783,
+                     0.00044351684288719036,
+                    -0.00000664263587520855) / (x*x*x);
+}
+
+// from https://stackoverflow.com/questions/6475373/optimizations-for-pow-with-const-non-integer-exponent
+
+
+
+//#define LINEAR2SRGB(in) (in <= 0.0031308 ? 12.92 * in : 1.055 * mpow(in, 1.0/GAMMA) - 0.055)
+//#define SRGB2LINEAR(in) (in <= 0.04045 ? in / 12.92 : mpow((in + 0.055) / 1.055, GAMMA))
+
+#define A_BLEND(top, bottom, alpha, max) \
+        max * linear_to_srgb(srgb_to_linear(1. * top / max)+ srgb_to_linear(1. * bottom / max)*(1.0 - (1. * alpha / max)))
+
+// Change lines:
+// #define ALPHA_NORMAL(mx, Sa, Da) (Sa + (Da * (mx - Sa)) / mx)
+// #define COLOR_NORMAL(mx, Sc, Sa, Dc, Da) ((Sc * Sa + Dc * (mx - Sa)) / mx)
+// To:
+#define ALPHA_NORMALS(mx, Sa, Da) ((Sa + (mx - Sa)*(mx - Sa)) / mx)
+#define COLOR_NORMALS(mx, Sc, Sa, Dc, Da) A_BLEND(Sc, Dc, Sa, mx)
+#define CHROMA_NORMALS COLOR_NORMALS
+
+
 static inline int   mabs(int32_t v) { return abs(v); }
 static inline int   mabs(int64_t v) { return llabs(v); }
 static inline float mabs(float v)   { return fabsf(v); }
@@ -366,6 +449,9 @@ ZTYP(float);	ZTYP(double);
 	case TRANSFER_HARDLIGHT:	FN(HARDLIGHT); \
 	case TRANSFER_SOFTLIGHT:	FN(SOFTLIGHT); \
 	case TRANSFER_DIFFERENCE:	FN(DIFFERENCE); \
+	case TRANSFER_REFLECT:		FN(REFLECT); \
+	case TRANSFER_AVERAGE:		FN(AVERAGE); \
+	case TRANSFER_NORMALS:		FN(NORMALS); \
 	}
 
 class OverlayKernel
diff --git a/cinelerra-5.1/cinelerra/overlayframe.inc b/cinelerra-5.1/cinelerra/overlayframe.inc
index 5f84036d..f155eb4a 100644
--- a/cinelerra-5.1/cinelerra/overlayframe.inc
+++ b/cinelerra-5.1/cinelerra/overlayframe.inc
@@ -24,7 +24,7 @@
 
 // Modes
 
-#define TRANSFER_TYPES 30
+#define TRANSFER_TYPES 33
 
 #define TRANSFER_NORMAL		0
 #define TRANSFER_ADDITION	1
@@ -56,6 +56,9 @@
 #define TRANSFER_HARDLIGHT	27
 #define TRANSFER_SOFTLIGHT	28
 #define TRANSFER_DIFFERENCE	29
+#define TRANSFER_REFLECT	30
+#define TRANSFER_AVERAGE	31
+#define TRANSFER_NORMALS	32
 
 
 // Interpolation types
diff --git a/cinelerra-5.1/cinelerra/patchbay.C b/cinelerra-5.1/cinelerra/patchbay.C
index c2ae534d..bc593617 100644
--- a/cinelerra-5.1/cinelerra/patchbay.C
+++ b/cinelerra-5.1/cinelerra/patchbay.C
@@ -218,6 +218,9 @@ void PatchBay::create_objects()
 		"mode_hardlight",
 		"mode_softlight",
 		"mode_difference",
+		"mode_reflect",
+		"mode_average",
+		"mode_normals",
 	};
 	for( int mode=0; mode<TRANSFER_TYPES; ++mode ) {
 		mode_icons[mode] = new BC_Pixmap(this,
diff --git a/cinelerra-5.1/cinelerra/vpatchgui.C b/cinelerra-5.1/cinelerra/vpatchgui.C
index 53ec27fb..d8e64c5c 100644
--- a/cinelerra-5.1/cinelerra/vpatchgui.C
+++ b/cinelerra-5.1/cinelerra/vpatchgui.C
@@ -354,6 +354,9 @@ void VModePatch::create_objects()
 	submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DIVIDE),   TRANSFER_DIVIDE));
 	submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_MULTIPLY), TRANSFER_MULTIPLY));
 	submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_REPLACE),  TRANSFER_REPLACE));
+	submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_REFLECT),  TRANSFER_REFLECT));
+	submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_AVERAGE),  TRANSFER_AVERAGE));
+	submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_NORMALS),  TRANSFER_NORMALS));
 	add_item(mode_item = new VModePatchItem(this, _("PorterDuff..."), -1));
 	mode_item->add_submenu(submenu = new VModePatchSubMenu(mode_item));
 	submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DST),	TRANSFER_DST));
@@ -436,6 +439,9 @@ const char* VModePatch::mode_to_text(int mode)
 	case TRANSFER_HARDLIGHT:	return _("Hardlight");
 	case TRANSFER_SOFTLIGHT:	return _("Softlight");
 	case TRANSFER_DIFFERENCE:	return _("Difference");
+	case TRANSFER_REFLECT:		return _("Reflect");
+	case TRANSFER_AVERAGE:		return _("Average");
+	case TRANSFER_NORMALS:		return _("NormalS");
 	}
 	return _("Normal");
 }


More information about the Cin mailing list