summaryrefslogtreecommitdiff
path: root/libavfilter
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2021-09-27 20:38:26 +0200
committerPaul B Mahol <onemda@gmail.com>2021-09-28 00:14:19 +0200
commitdd190195007093da57959c68c740e729e1048c24 (patch)
tree83fff085b837d6449df8db41129d733a5be3c900 /libavfilter
parent524407af0c3993a36fb8399e5ba7fa07b731b57c (diff)
avfilter/vf_blend: refactor blend modes
Diffstat (limited to 'libavfilter')
-rw-r--r--libavfilter/blend_modes.c142
-rw-r--r--libavfilter/vf_blend.c311
2 files changed, 165 insertions, 288 deletions
diff --git a/libavfilter/blend_modes.c b/libavfilter/blend_modes.c
new file mode 100644
index 0000000000..d75560185c
--- /dev/null
+++ b/libavfilter/blend_modes.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2013 Paul B Mahol
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/common.h"
+#include "libavutil/intfloat.h"
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+#include "video.h"
+#include "blend.h"
+
+#undef PIXEL
+#undef MAX
+#undef HALF
+#undef CLIP
+
+#if DEPTH == 8
+#define PIXEL uint8_t
+#define MAX 255
+#define HALF 128
+#define CLIP(x) (av_clip_uint8(x))
+#elif DEPTH == 32
+#define PIXEL float
+#define MAX 1.f
+#define HALF 0.5f
+#define CLIP(x) (x)
+#else
+#define PIXEL uint16_t
+#define MAX ((1 << DEPTH) - 1)
+#define HALF (1 << (DEPTH - 1))
+#define CLIP(x) ((int)av_clip_uintp2(x, DEPTH))
+#endif
+
+#undef MULTIPLY
+#undef SCREEN
+#undef BURN
+#undef DODGE
+#undef INT2FLOAT
+#undef FLOAT2INT
+#undef MDIV
+
+#if DEPTH < 32
+#define MULTIPLY(x, a, b) ((x) * (((a) * (b)) / MAX))
+#define SCREEN(x, a, b) (MAX - (x) * ((MAX - (a)) * (MAX - (b)) / MAX))
+#define BURN(a, b) (((a) == 0) ? (a) : FFMAX(0, MAX - ((MAX - (b)) << DEPTH) / (a)))
+#define DODGE(a, b) (((a) == MAX) ? (a) : FFMIN(MAX, (((b) << DEPTH) / (MAX - (a)))))
+#define INT2FLOAT(x) (x)
+#define FLOAT2INT(x) (x)
+#define MDIV (0.125f * (1 << DEPTH))
+#else
+#define MULTIPLY(x, a, b) ((x) * (((a) * (b)) / 1.0))
+#define SCREEN(x, a, b) (1.0 - (x) * ((1.0 - (a)) * (1.0 - (b)) / 1.0))
+#define BURN(a, b) (((a) <= 0.0) ? (a) : FFMAX(0.0, 1.0 - (1.0 - (b)) / (a)))
+#define DODGE(a, b) (((a) >= 1.0) ? (a) : FFMIN(1.0, ((b) / (1.0 - (a)))))
+#define INT2FLOAT(x) av_int2float(x)
+#define FLOAT2INT(x) av_float2int(x)
+#define MDIV 0.125f
+#endif
+
+#define A top[j]
+#define B bottom[j]
+
+#define fn2(a, b) blend_##a##_##b##bit
+#define fn1(name, depth) fn2(name, depth)
+#define fn0(name) fn1(name, DEPTH)
+
+#define fn(NAME, EXPR) \
+static void fn0(NAME)(const uint8_t *_top, ptrdiff_t top_linesize, \
+ const uint8_t *_bottom, ptrdiff_t bottom_linesize, \
+ uint8_t *_dst, ptrdiff_t dst_linesize, \
+ ptrdiff_t width, ptrdiff_t height, \
+ FilterParams *param, double *values, int starty) \
+{ \
+ const PIXEL *top = (PIXEL *)_top; \
+ const PIXEL *bottom = (PIXEL *)_bottom; \
+ PIXEL *dst = (PIXEL *)_dst; \
+ const float opacity = param->opacity; \
+ \
+ dst_linesize /= sizeof(PIXEL); \
+ top_linesize /= sizeof(PIXEL); \
+ bottom_linesize /= sizeof(PIXEL); \
+ \
+ for (int i = 0; i < height; i++) { \
+ for (int j = 0; j < width; j++) { \
+ dst[j] = top[j] + ((EXPR)-top[j]) * opacity; \
+ } \
+ dst += dst_linesize; \
+ top += top_linesize; \
+ bottom += bottom_linesize; \
+ } \
+}
+
+fn(addition, FFMIN(MAX, A + B))
+fn(grainmerge, CLIP(A + B - HALF))
+fn(average, (A + B) / 2)
+fn(subtract, FFMAX(0, A - B))
+fn(multiply, MULTIPLY(1, A, B))
+fn(multiply128,CLIP((A - HALF) * B / MDIV + HALF))
+fn(negation, MAX - FFABS(MAX - A - B))
+fn(extremity, FFABS(MAX - A - B))
+fn(difference, FFABS(A - B))
+fn(grainextract, CLIP(HALF + A - B))
+fn(screen, SCREEN(1, A, B))
+fn(overlay, (A < HALF) ? MULTIPLY(2, A, B) : SCREEN(2, A, B))
+fn(hardlight, (B < HALF) ? MULTIPLY(2, B, A) : SCREEN(2, B, A))
+fn(hardmix, (A < (MAX - B)) ? 0: MAX)
+fn(heat, (A == 0) ? 0 : MAX - FFMIN(((MAX - B) * (MAX - B)) / A, MAX))
+fn(freeze, (B == 0) ? 0 : MAX - FFMIN(((MAX - A) * (MAX - A)) / B, MAX))
+fn(darken, FFMIN(A, B))
+fn(lighten, FFMAX(A, B))
+fn(divide, CLIP(B == 0 ? MAX : MAX * A / B))
+fn(dodge, DODGE(A, B))
+fn(burn, BURN(A, B))
+fn(softlight, CLIP(A * A / MAX + (2 * (B * ((A * (MAX - A)) / MAX) / MAX))))
+fn(exclusion, A + B - 2 * A * B / MAX)
+fn(pinlight, (B < HALF) ? FFMIN(A, 2 * B) : FFMAX(A, 2 * (B - HALF)))
+fn(phoenix, FFMIN(A, B) - FFMAX(A, B) + MAX)
+fn(reflect, (B == MAX) ? B : FFMIN(MAX, (A * A / (MAX - B))))
+fn(glow, (A == MAX) ? A : FFMIN(MAX, (B * B / (MAX - A))))
+fn(and, INT2FLOAT(FLOAT2INT(A) & FLOAT2INT(B)))
+fn(or, INT2FLOAT(FLOAT2INT(A) | FLOAT2INT(B)))
+fn(xor, INT2FLOAT(FLOAT2INT(A) ^ FLOAT2INT(B)))
+fn(vividlight, (A < HALF) ? BURN(2 * A, B) : DODGE(2 * (A - HALF), B))
+fn(linearlight,CLIP((B < HALF) ? B + 2 * A - MAX : B + 2 * (A - HALF)))
+fn(softdifference,CLIP((A > B) ? (B == MAX) ? 0 : (A - B) * MAX / (MAX - B) : (B == 0) ? 0 : (B - A) * MAX / B))
diff --git a/libavfilter/vf_blend.c b/libavfilter/vf_blend.c
index 23cd22ff6f..e4569a255e 100644
--- a/libavfilter/vf_blend.c
+++ b/libavfilter/vf_blend.c
@@ -33,6 +33,29 @@
#define TOP 0
#define BOTTOM 1
+#define DEPTH 8
+#include "blend_modes.c"
+
+#undef DEPTH
+#define DEPTH 9
+#include "blend_modes.c"
+
+#undef DEPTH
+#define DEPTH 10
+#include "blend_modes.c"
+
+#undef DEPTH
+#define DEPTH 12
+#include "blend_modes.c"
+
+#undef DEPTH
+#define DEPTH 16
+#include "blend_modes.c"
+
+#undef DEPTH
+#define DEPTH 32
+#include "blend_modes.c"
+
typedef struct BlendContext {
const AVClass *class;
FFFrameSync fs;
@@ -172,294 +195,6 @@ BLEND_NORMAL(8bit, uint8_t)
BLEND_NORMAL(16bit, uint16_t)
BLEND_NORMAL(32bit, float)
-#define DEFINE_BLEND(name, expr, depth, type) \
-static void blend_## name##_##depth##bit(const uint8_t *_top, ptrdiff_t top_linesize, \
- const uint8_t *_bottom, ptrdiff_t bottom_linesize, \
- uint8_t *_dst, ptrdiff_t dst_linesize, \
- ptrdiff_t width, ptrdiff_t height, \
- FilterParams *param, double *values, int starty) \
-{ \
- const type *top = (type*)_top; \
- const type *bottom = (type*)_bottom; \
- type *dst = (type*)_dst; \
- const float opacity = param->opacity; \
- \
- dst_linesize /= sizeof(type); \
- top_linesize /= sizeof(type); \
- bottom_linesize /= sizeof(type); \
- \
- for (int i = 0; i < height; i++) { \
- for (int j = 0; j < width; j++) { \
- dst[j] = top[j] + ((expr) - top[j]) * opacity; \
- } \
- dst += dst_linesize; \
- top += top_linesize; \
- bottom += bottom_linesize; \
- } \
-}
-
-#define A top[j]
-#define B bottom[j]
-
-#define MULTIPLY(x, a, b) ((x) * (((a) * (b)) / 255))
-#define SCREEN(x, a, b) (255 - (x) * ((255 - (a)) * (255 - (b)) / 255))
-#define BURN(a, b) (((a) == 0) ? (a) : FFMAX(0, 255 - ((255 - (b)) << 8) / (a)))
-#define DODGE(a, b) (((a) == 255) ? (a) : FFMIN(255, (((b) << 8) / (255 - (a)))))
-
-DEFINE_BLEND(addition, FFMIN(255, A + B), 8, uint8_t)
-DEFINE_BLEND(grainmerge, av_clip_uint8(A + B - 128), 8, uint8_t)
-DEFINE_BLEND(average, (A + B) / 2, 8, uint8_t)
-DEFINE_BLEND(subtract, FFMAX(0, A - B), 8, uint8_t)
-DEFINE_BLEND(multiply, MULTIPLY(1, A, B), 8, uint8_t)
-DEFINE_BLEND(multiply128,av_clip_uint8((A - 128) * B / 32. + 128), 8, uint8_t)
-DEFINE_BLEND(negation, 255 - FFABS(255 - A - B), 8, uint8_t)
-DEFINE_BLEND(extremity, FFABS(255 - A - B), 8, uint8_t)
-DEFINE_BLEND(difference, FFABS(A - B), 8, uint8_t)
-DEFINE_BLEND(grainextract, av_clip_uint8(128 + A - B), 8, uint8_t)
-DEFINE_BLEND(screen, SCREEN(1, A, B), 8, uint8_t)
-DEFINE_BLEND(overlay, (A < 128) ? MULTIPLY(2, A, B) : SCREEN(2, A, B), 8, uint8_t)
-DEFINE_BLEND(hardlight, (B < 128) ? MULTIPLY(2, B, A) : SCREEN(2, B, A), 8, uint8_t)
-DEFINE_BLEND(hardmix, (A < (255 - B)) ? 0: 255, 8, uint8_t)
-DEFINE_BLEND(heat, (A == 0) ? 0 : 255 - FFMIN(((255 - B) * (255 - B)) / A, 255), 8, uint8_t)
-DEFINE_BLEND(freeze, (B == 0) ? 0 : 255 - FFMIN(((255 - A) * (255 - A)) / B, 255), 8, uint8_t)
-DEFINE_BLEND(darken, FFMIN(A, B), 8, uint8_t)
-DEFINE_BLEND(lighten, FFMAX(A, B), 8, uint8_t)
-DEFINE_BLEND(divide, av_clip_uint8(B == 0 ? 255 : 255 * A / B), 8, uint8_t)
-DEFINE_BLEND(dodge, DODGE(A, B), 8, uint8_t)
-DEFINE_BLEND(burn, BURN(A, B), 8, uint8_t)
-DEFINE_BLEND(softlight, (A > 127) ? B + (255 - B) * (A - 127.5) / 127.5 * (0.5 - fabs(B - 127.5) / 255): B - B * ((127.5 - A) / 127.5) * (0.5 - fabs(B - 127.5)/255), 8, uint8_t)
-DEFINE_BLEND(exclusion, A + B - 2 * A * B / 255, 8, uint8_t)
-DEFINE_BLEND(pinlight, (B < 128) ? FFMIN(A, 2 * B) : FFMAX(A, 2 * (B - 128)), 8, uint8_t)
-DEFINE_BLEND(phoenix, FFMIN(A, B) - FFMAX(A, B) + 255, 8, uint8_t)
-DEFINE_BLEND(reflect, (B == 255) ? B : FFMIN(255, (A * A / (255 - B))), 8, uint8_t)
-DEFINE_BLEND(glow, (A == 255) ? A : FFMIN(255, (B * B / (255 - A))), 8, uint8_t)
-DEFINE_BLEND(and, A & B, 8, uint8_t)
-DEFINE_BLEND(or, A | B, 8, uint8_t)
-DEFINE_BLEND(xor, A ^ B, 8, uint8_t)
-DEFINE_BLEND(vividlight, (A < 128) ? BURN(2 * A, B) : DODGE(2 * (A - 128), B), 8, uint8_t)
-DEFINE_BLEND(linearlight,av_clip_uint8((B < 128) ? B + 2 * A - 255 : B + 2 * (A - 128)), 8, uint8_t)
-DEFINE_BLEND(softdifference,av_clip_uint8((A > B) ? (B == 255) ? 0 : (A - B) * 255 / (255 - B) : (B == 0) ? 0 : (B - A) * 255 / B), 8, uint8_t)
-
-#undef MULTIPLY
-#undef SCREEN
-#undef BURN
-#undef DODGE
-
-#define MULTIPLY(x, a, b) ((x) * (((a) * (b)) / 65535))
-#define SCREEN(x, a, b) (65535 - (x) * ((65535 - (a)) * (65535 - (b)) / 65535))
-#define BURN(a, b) (((a) == 0) ? (a) : FFMAX(0, 65535 - ((65535 - (b)) << 16) / (a)))
-#define DODGE(a, b) (((a) == 65535) ? (a) : FFMIN(65535, (((b) << 16) / (65535 - (a)))))
-
-DEFINE_BLEND(addition, FFMIN(65535, A + B), 16, uint16_t)
-DEFINE_BLEND(grainmerge, av_clip_uint16(A + B - 32768), 16, uint16_t)
-DEFINE_BLEND(average, (A + B) / 2, 16, uint16_t)
-DEFINE_BLEND(subtract, FFMAX(0, A - B), 16, uint16_t)
-DEFINE_BLEND(multiply, MULTIPLY(1, A, B), 16, uint16_t)
-DEFINE_BLEND(multiply128, av_clip_uint16((A - 32768) * B / 8192. + 32768), 16, uint16_t)
-DEFINE_BLEND(negation, 65535 - FFABS(65535 - A - B), 16, uint16_t)
-DEFINE_BLEND(extremity, FFABS(65535 - A - B), 16, uint16_t)
-DEFINE_BLEND(difference, FFABS(A - B), 16, uint16_t)
-DEFINE_BLEND(grainextract, av_clip_uint16(32768 + A - B), 16, uint16_t)
-DEFINE_BLEND(screen, SCREEN(1, A, B), 16, uint16_t)
-DEFINE_BLEND(overlay, (A < 32768) ? MULTIPLY(2, A, B) : SCREEN(2, A, B), 16, uint16_t)
-DEFINE_BLEND(hardlight, (B < 32768) ? MULTIPLY(2, B, A) : SCREEN(2, B, A), 16, uint16_t)
-DEFINE_BLEND(hardmix, (A < (65535 - B)) ? 0: 65535, 16, uint16_t)
-DEFINE_BLEND(heat, (A == 0) ? 0 : 65535 - FFMIN(((65535 - B) * (65535 - B)) / A, 65535), 16, uint16_t)
-DEFINE_BLEND(freeze, (B == 0) ? 0 : 65535 - FFMIN(((65535 - A) * (65535 - A)) / B, 65535), 16, uint16_t)
-DEFINE_BLEND(darken, FFMIN(A, B), 16, uint16_t)
-DEFINE_BLEND(lighten, FFMAX(A, B), 16, uint16_t)
-DEFINE_BLEND(divide, av_clip_uint16(B == 0 ? 65535 : 65535 * A / B), 16, uint16_t)
-DEFINE_BLEND(dodge, DODGE(A, B), 16, uint16_t)
-DEFINE_BLEND(burn, BURN(A, B), 16, uint16_t)
-DEFINE_BLEND(softlight, (A > 32767) ? B + (65535 - B) * (A - 32767.5) / 32767.5 * (0.5 - fabs(B - 32767.5) / 65535): B - B * ((32767.5 - A) / 32767.5) * (0.5 - fabs(B - 32767.5)/65535), 16, uint16_t)
-DEFINE_BLEND(exclusion, A + B - 2 * A * B / 65535, 16, uint16_t)
-DEFINE_BLEND(pinlight, (B < 32768) ? FFMIN(A, 2 * B) : FFMAX(A, 2 * (B - 32768)), 16, uint16_t)
-DEFINE_BLEND(phoenix, FFMIN(A, B) - FFMAX(A, B) + 65535, 16, uint16_t)
-DEFINE_BLEND(reflect, (B == 65535) ? B : FFMIN(65535, (A * A / (65535 - B))), 16, uint16_t)
-DEFINE_BLEND(glow, (A == 65535) ? A : FFMIN(65535, (B * B / (65535 - A))), 16, uint16_t)
-DEFINE_BLEND(and, A & B, 16, uint16_t)
-DEFINE_BLEND(or, A | B, 16, uint16_t)
-DEFINE_BLEND(xor, A ^ B, 16, uint16_t)
-DEFINE_BLEND(vividlight, (A < 32768) ? BURN(2 * A, B) : DODGE(2 * (A - 32768), B), 16, uint16_t)
-DEFINE_BLEND(linearlight,av_clip_uint16((B < 32768) ? B + 2 * A - 65535 : B + 2 * (A - 32768)), 16, uint16_t)
-DEFINE_BLEND(softdifference,av_clip_uint16((A > B) ? (B == 65535) ? 0 : (A - B) * 65535 / (65535 - B) : (B == 0) ? 0 : (B - A) * 65535 / B), 16, uint16_t)
-
-#undef MULTIPLY
-#undef SCREEN
-#undef BURN
-#undef DODGE
-
-#define MULTIPLY(x, a, b) ((x) * (((a) * (b)) / 1023))
-#define SCREEN(x, a, b) (1023 - (x) * ((1023 - (a)) * (1023 - (b)) / 1023))
-#define BURN(a, b) (((a) == 0) ? (a) : FFMAX(0, 1023 - ((1023 - (b)) << 10) / (a)))
-#define DODGE(a, b) (((a) == 1023) ? (a) : FFMIN(1023, (((b) << 10) / (1023 - (a)))))
-
-DEFINE_BLEND(addition, FFMIN(1023, A + B), 10, uint16_t)
-DEFINE_BLEND(grainmerge, (int)av_clip_uintp2(A + B - 512, 10), 10, uint16_t)
-DEFINE_BLEND(average, (A + B) / 2, 10, uint16_t)
-DEFINE_BLEND(subtract, FFMAX(0, A - B), 10, uint16_t)
-DEFINE_BLEND(multiply, MULTIPLY(1, A, B), 10, uint16_t)
-DEFINE_BLEND(multiply128, (int)av_clip_uintp2((A - 512) * B / 128. + 512, 10), 10, uint16_t)
-DEFINE_BLEND(negation, 1023 - FFABS(1023 - A - B), 10, uint16_t)
-DEFINE_BLEND(extremity, FFABS(1023 - A - B), 10, uint16_t)
-DEFINE_BLEND(difference, FFABS(A - B), 10, uint16_t)
-DEFINE_BLEND(grainextract, (int)av_clip_uintp2(512 + A - B, 10), 10, uint16_t)
-DEFINE_BLEND(screen, SCREEN(1, A, B), 10, uint16_t)
-DEFINE_BLEND(overlay, (A < 512) ? MULTIPLY(2, A, B) : SCREEN(2, A, B), 10, uint16_t)
-DEFINE_BLEND(hardlight, (B < 512) ? MULTIPLY(2, B, A) : SCREEN(2, B, A), 10, uint16_t)
-DEFINE_BLEND(hardmix, (A < (1023 - B)) ? 0: 1023, 10, uint16_t)
-DEFINE_BLEND(heat, (A == 0) ? 0 : 1023 - FFMIN(((1023 - B) * (1023 - B)) / A, 1023), 10, uint16_t)
-DEFINE_BLEND(freeze, (B == 0) ? 0 : 1023 - FFMIN(((1023 - A) * (1023 - A)) / B, 1023), 10, uint16_t)
-DEFINE_BLEND(darken, FFMIN(A, B), 10, uint16_t)
-DEFINE_BLEND(lighten, FFMAX(A, B), 10, uint16_t)
-DEFINE_BLEND(divide, (int)av_clip_uintp2(B == 0 ? 1023 : 1023 * A / B, 10), 10, uint16_t)
-DEFINE_BLEND(dodge, DODGE(A, B), 10, uint16_t)
-DEFINE_BLEND(burn, BURN(A, B), 10, uint16_t)
-DEFINE_BLEND(softlight, (A > 511) ? B + (1023 - B) * (A - 511.5) / 511.5 * (0.5 - fabs(B - 511.5) / 1023): B - B * ((511.5 - A) / 511.5) * (0.5 - fabs(B - 511.5)/1023), 10, uint16_t)
-DEFINE_BLEND(exclusion, A + B - 2 * A * B / 1023, 10, uint16_t)
-DEFINE_BLEND(pinlight, (B < 512) ? FFMIN(A, 2 * B) : FFMAX(A, 2 * (B - 512)), 10, uint16_t)
-DEFINE_BLEND(phoenix, FFMIN(A, B) - FFMAX(A, B) + 1023, 10, uint16_t)
-DEFINE_BLEND(reflect, (B == 1023) ? B : FFMIN(1023, (A * A / (1023 - B))), 10, uint16_t)
-DEFINE_BLEND(glow, (A == 1023) ? A : FFMIN(1023, (B * B / (1023 - A))), 10, uint16_t)
-DEFINE_BLEND(and, A & B, 10, uint16_t)
-DEFINE_BLEND(or, A | B, 10, uint16_t)
-DEFINE_BLEND(xor, A ^ B, 10, uint16_t)
-DEFINE_BLEND(vividlight, (A < 512) ? BURN(2 * A, B) : DODGE(2 * (A - 512), B), 10, uint16_t)
-DEFINE_BLEND(linearlight,(int)av_clip_uintp2((B < 512) ? B + 2 * A - 1023 : B + 2 * (A - 512), 10), 10, uint16_t)
-DEFINE_BLEND(softdifference,(int)av_clip_uintp2((A > B) ? (B == 1023) ? 0 : (A - B) * 1023 / (1023 - B) : (B == 0) ? 0 : (B - A) * 1023 / B, 10), 10, uint16_t)
-
-#undef MULTIPLY
-#undef SCREEN
-#undef BURN
-#undef DODGE
-
-#define MULTIPLY(x, a, b) ((x) * (((a) * (b)) / 4095))
-#define SCREEN(x, a, b) (4095 - (x) * ((4095 - (a)) * (4095 - (b)) / 4095))
-#define BURN(a, b) (((a) == 0) ? (a) : FFMAX(0, 4095 - ((4095 - (b)) << 12) / (a)))
-#define DODGE(a, b) (((a) == 4095) ? (a) : FFMIN(4095, (((b) << 12) / (4095 - (a)))))
-
-DEFINE_BLEND(addition, FFMIN(4095, A + B), 12, uint16_t)
-DEFINE_BLEND(grainmerge, (int)av_clip_uintp2(A + B - 2048, 12), 12, uint16_t)
-DEFINE_BLEND(average, (A + B) / 2, 12, uint16_t)
-DEFINE_BLEND(subtract, FFMAX(0, A - B), 12, uint16_t)
-DEFINE_BLEND(multiply, MULTIPLY(1, A, B), 12, uint16_t)
-DEFINE_BLEND(multiply128, (int)av_clip_uintp2((A - 2048) * B / 512. + 2048, 12), 12, uint16_t)
-DEFINE_BLEND(negation, 4095 - FFABS(4095 - A - B), 12, uint16_t)
-DEFINE_BLEND(extremity, FFABS(4095 - A - B), 12, uint16_t)
-DEFINE_BLEND(difference, FFABS(A - B), 12, uint16_t)
-DEFINE_BLEND(grainextract, (int)av_clip_uintp2(2048 + A - B, 12), 12, uint16_t)
-DEFINE_BLEND(screen, SCREEN(1, A, B), 12, uint16_t)
-DEFINE_BLEND(overlay, (A < 2048) ? MULTIPLY(2, A, B) : SCREEN(2, A, B), 12, uint16_t)
-DEFINE_BLEND(hardlight, (B < 2048) ? MULTIPLY(2, B, A) : SCREEN(2, B, A), 12, uint16_t)
-DEFINE_BLEND(hardmix, (A < (4095 - B)) ? 0: 4095, 12, uint16_t)
-DEFINE_BLEND(heat, (A == 0) ? 0 : 4095 - FFMIN(((4095 - B) * (4095 - B)) / A, 4095), 12, uint16_t)
-DEFINE_BLEND(freeze, (B == 0) ? 0 : 4095 - FFMIN(((4095 - A) * (4095 - A)) / B, 4095), 12, uint16_t)
-DEFINE_BLEND(darken, FFMIN(A, B), 12, uint16_t)
-DEFINE_BLEND(lighten, FFMAX(A, B), 12, uint16_t)
-DEFINE_BLEND(divide, (int)av_clip_uintp2(B == 0 ? 4095 : 4095 * A / B, 12), 12, uint16_t)
-DEFINE_BLEND(dodge, DODGE(A, B), 12, uint16_t)
-DEFINE_BLEND(burn, BURN(A, B), 12, uint16_t)
-DEFINE_BLEND(softlight, (A > 2047) ? B + (4095 - B) * (A - 2047.5) / 2047.5 * (0.5 - fabs(B - 2047.5) / 4095): B - B * ((2047.5 - A) / 2047.5) * (0.5 - fabs(B - 2047.5)/4095), 12, uint16_t)
-DEFINE_BLEND(exclusion, A + B - 2 * A * B / 4095, 12, uint16_t)
-DEFINE_BLEND(pinlight, (B < 2048) ? FFMIN(A, 2 * B) : FFMAX(A, 2 * (B - 2048)), 12, uint16_t)
-DEFINE_BLEND(phoenix, FFMIN(A, B) - FFMAX(A, B) + 4095, 12, uint16_t)
-DEFINE_BLEND(reflect, (B == 4095) ? B : FFMIN(4095, (A * A / (4095 - B))), 12, uint16_t)
-DEFINE_BLEND(glow, (A == 4095) ? A : FFMIN(4095, (B * B / (4095 - A))), 12, uint16_t)
-DEFINE_BLEND(and, A & B, 12, uint16_t)
-DEFINE_BLEND(or, A | B, 12, uint16_t)
-DEFINE_BLEND(xor, A ^ B, 12, uint16_t)
-DEFINE_BLEND(vividlight, (A < 2048) ? BURN(2 * A, B) : DODGE(2 * (A - 2048), B), 12, uint16_t)
-DEFINE_BLEND(linearlight,(int)av_clip_uintp2((B < 2048) ? B + 2 * A - 4095 : B + 2 * (A - 2048), 12), 12, uint16_t)
-DEFINE_BLEND(softdifference,(int)av_clip_uintp2((A > B) ? (B == 4095) ? 0 : (A - B) * 4095 / (4095 - B) : (B == 0) ? 0 : (B - A) * 4095 / B, 12), 12, uint16_t)
-
-#undef MULTIPLY
-#undef SCREEN
-#undef BURN
-#undef DODGE
-
-#define MULTIPLY(x, a, b) ((x) * (((a) * (b)) / 511))
-#define SCREEN(x, a, b) (511 - (x) * ((511 - (a)) * (511 - (b)) / 511))
-#define BURN(a, b) (((a) == 0) ? (a) : FFMAX(0, 511 - ((511 - (b)) << 9) / (a)))
-#define DODGE(a, b) (((a) == 511) ? (a) : FFMIN(511, (((b) << 9) / (511 - (a)))))
-
-DEFINE_BLEND(addition, FFMIN(511, A + B), 9, uint16_t)
-DEFINE_BLEND(grainmerge, (int)av_clip_uintp2(A + B - 256, 9), 9, uint16_t)
-DEFINE_BLEND(average, (A + B) / 2, 9, uint16_t)
-DEFINE_BLEND(subtract, FFMAX(0, A - B), 9, uint16_t)
-DEFINE_BLEND(multiply, MULTIPLY(1, A, B), 9, uint16_t)
-DEFINE_BLEND(multiply128, (int)av_clip_uintp2((A - 256) * B / 64. + 256, 9), 9, uint16_t)
-DEFINE_BLEND(negation, 511 - FFABS(511 - A - B), 9, uint16_t)
-DEFINE_BLEND(extremity, FFABS(511 - A - B), 9, uint16_t)
-DEFINE_BLEND(difference, FFABS(A - B), 9, uint16_t)
-DEFINE_BLEND(grainextract, (int)av_clip_uintp2(256 + A - B, 9), 9, uint16_t)
-DEFINE_BLEND(screen, SCREEN(1, A, B), 9, uint16_t)
-DEFINE_BLEND(overlay, (A < 256) ? MULTIPLY(2, A, B) : SCREEN(2, A, B), 9, uint16_t)
-DEFINE_BLEND(hardlight, (B < 256) ? MULTIPLY(2, B, A) : SCREEN(2, B, A), 9, uint16_t)
-DEFINE_BLEND(hardmix, (A < (511 - B)) ? 0: 511, 9, uint16_t)
-DEFINE_BLEND(heat, (A == 0) ? 0 : 511 - FFMIN(((511 - B) * (511 - B)) / A, 511), 9, uint16_t)
-DEFINE_BLEND(freeze, (B == 0) ? 0 : 511 - FFMIN(((511 - A) * (511 - A)) / B, 511), 9, uint16_t)
-DEFINE_BLEND(darken, FFMIN(A, B), 9, uint16_t)
-DEFINE_BLEND(lighten, FFMAX(A, B), 9, uint16_t)
-DEFINE_BLEND(divide, (int)av_clip_uintp2(B == 0 ? 511 : 511 * A / B, 9), 9, uint16_t)
-DEFINE_BLEND(dodge, DODGE(A, B), 9, uint16_t)
-DEFINE_BLEND(burn, BURN(A, B), 9, uint16_t)
-DEFINE_BLEND(softlight, (A > 511) ? B + (511 - B) * (A - 511.5) / 511.5 * (0.5 - fabs(B - 511.5) / 511): B - B * ((511.5 - A) / 511.5) * (0.5 - fabs(B - 511.5)/511), 9, uint16_t)
-DEFINE_BLEND(exclusion, A + B - 2 * A * B / 511, 9, uint16_t)
-DEFINE_BLEND(pinlight, (B < 256) ? FFMIN(A, 2 * B) : FFMAX(A, 2 * (B - 256)), 9, uint16_t)
-DEFINE_BLEND(phoenix, FFMIN(A, B) - FFMAX(A, B) + 511, 9, uint16_t)
-DEFINE_BLEND(reflect, (B == 511) ? B : FFMIN(511, (A * A / (511 - B))), 9, uint16_t)
-DEFINE_BLEND(glow, (A == 511) ? A : FFMIN(511, (B * B / (511 - A))), 9, uint16_t)
-DEFINE_BLEND(and, A & B, 9, uint16_t)
-DEFINE_BLEND(or, A | B, 9, uint16_t)
-DEFINE_BLEND(xor, A ^ B, 9, uint16_t)
-DEFINE_BLEND(vividlight, (A < 256) ? BURN(2 * A, B) : DODGE(2 * (A - 256), B), 9, uint16_t)
-DEFINE_BLEND(linearlight,(int)av_clip_uintp2((B < 256) ? B + 2 * A - 511 : B + 2 * (A - 256), 9), 9, uint16_t)
-DEFINE_BLEND(softdifference,(int)av_clip_uintp2((A > B) ? (A - B) * 511 / (511 - B) : (B == 0) ? 0 : (B - A) * 511 / B, 9), 9, uint16_t)
-
-#undef MULTIPLY
-#undef SCREEN
-#undef BURN
-#undef DODGE
-
-#define MULTIPLY(x, a, b) ((x) * (((a) * (b)) / 1.0))
-#define SCREEN(x, a, b) (1.0 - (x) * ((1.0 - (a)) * (1.0 - (b)) / 1.0))
-#define BURN(a, b) (((a) <= 0.0) ? (a) : FFMAX(0.0, 1.0 - (1.0 - (b)) / (a)))
-#define DODGE(a, b) (((a) >= 1.0) ? (a) : FFMIN(1.0, ((b) / (1.0 - (a)))))
-
-DEFINE_BLEND(addition, A + B, 32, float)
-DEFINE_BLEND(grainmerge, A + B - 0.5, 32, float)
-DEFINE_BLEND(average, (A + B) / 2, 32, float)
-DEFINE_BLEND(subtract, A - B, 32, float)
-DEFINE_BLEND(multiply, A * B, 32, float)
-DEFINE_BLEND(multiply128, (A - 0.5) * B / 0.125 + 0.5, 32, float)
-DEFINE_BLEND(negation, 1.0 - FFABS(1.0 - A - B), 32, float)
-DEFINE_BLEND(extremity, FFABS(1.0 - A - B), 32, float)
-DEFINE_BLEND(difference, FFABS(A - B), 32, float)
-DEFINE_BLEND(grainextract, 0.5 + A - B, 32, float)
-DEFINE_BLEND(screen, SCREEN(1, A, B), 32, float)
-DEFINE_BLEND(overlay, (A < 0.5) ? MULTIPLY(2, A, B) : SCREEN(2, A, B), 32, float)
-DEFINE_BLEND(hardlight, (B < 0.5) ? MULTIPLY(2, B, A) : SCREEN(2, B, A), 32, float)
-DEFINE_BLEND(hardmix, (A < (1.0 - B)) ? 0: 1.0, 32, float)
-DEFINE_BLEND(heat, (A == 0) ? 0 : 1.0 - FFMIN(((1.0 - B) * (1.0 - B)) / A, 1.0), 32, float)
-DEFINE_BLEND(freeze, (B == 0) ? 0 : 1.0 - FFMIN(((1.0 - A) * (1.0 - A)) / B, 1.0), 32, float)
-DEFINE_BLEND(darken, FFMIN(A, B), 32, float)
-DEFINE_BLEND(lighten, FFMAX(A, B), 32, float)
-DEFINE_BLEND(divide, B == 0 ? 1.0 : 1.0 * A / B, 32, float)
-DEFINE_BLEND(dodge, DODGE(A, B), 32, float)
-DEFINE_BLEND(burn, BURN(A, B), 32, float)
-DEFINE_BLEND(softlight, (A > 0.5) ? B + (1.0 - B) * (A - 0.5) / 0.5 * (0.5 - fabs(B - 0.5) / 1.0): B - B * ((0.5 - A) / 0.5) * (0.5 - fabs(B - 0.5)/1.0), 32, float)
-DEFINE_BLEND(exclusion, A + B - 2 * A * B / 1.0, 32, float)
-DEFINE_BLEND(pinlight, (B < 0.5) ? FFMIN(A, 2 * B) : FFMAX(A, 2 * (B - 0.5)), 32, float)
-DEFINE_BLEND(phoenix, FFMIN(A, B) - FFMAX(A, B) + 1.0, 32, float)
-DEFINE_BLEND(reflect, (B == 1.0) ? B : FFMIN(1.0, (A * A / (1.0 - B))), 32, float)
-DEFINE_BLEND(glow, (A == 1.0) ? A : FFMIN(1.0, (B * B / (1.0 - A))), 32, float)
-DEFINE_BLEND(and, av_int2float(av_float2int(A) & av_float2int(B)), 32, float)
-DEFINE_BLEND(or, av_int2float(av_float2int(A) | av_float2int(B)), 32, float)
-DEFINE_BLEND(xor, av_int2float(av_float2int(A) ^ av_float2int(B)), 32, float)
-DEFINE_BLEND(vividlight, (A < 0.5) ? BURN(2 * A, B) : DODGE(2 * (A - 0.5), B), 32, float)
-DEFINE_BLEND(linearlight,(B < 0.5) ? B + 2 * A - 1.0 : B + 2 * (A - 0.5), 32, float)
-DEFINE_BLEND(softdifference, (A > B) ? (B == 1.f) ? 0.f : (A - B) / (1.f - B) : (B == 0.f) ? 0.f : (B - A) / B, 32, float)
-
#define DEFINE_BLEND_EXPR(type, name, div) \
static void blend_expr_## name(const uint8_t *_top, ptrdiff_t top_linesize, \
const uint8_t *_bottom, ptrdiff_t bottom_linesize, \