From 93d60cc0fdf746cc03b4d7a9e45744c2c424439b Mon Sep 17 00:00:00 2001 From: Good Guy Date: Sat, 1 Oct 2016 13:29:11 -0600 Subject: [PATCH] graphic art overlay modes, pref window resize, submenu fixes --- cinelerra-5.1/cinelerra/Makefile | 3 + cinelerra-5.1/cinelerra/overlaydirect.C | 122 ++ cinelerra-5.1/cinelerra/overlayframe.C | 901 +-------- cinelerra-5.1/cinelerra/overlayframe.C.clamp | 1796 ----------------- cinelerra-5.1/cinelerra/overlayframe.C.float | 1723 ---------------- .../cinelerra/overlayframe.C.floattable | 1769 ---------------- cinelerra-5.1/cinelerra/overlayframe.C.int | 1749 ---------------- cinelerra-5.1/cinelerra/overlayframe.h | 340 +++- cinelerra-5.1/cinelerra/overlayframe.h.clamp | 381 ---- cinelerra-5.1/cinelerra/overlayframe.h.float | 347 ---- .../cinelerra/overlayframe.h.floattable | 376 ---- cinelerra-5.1/cinelerra/overlayframe.h.int | 352 ---- cinelerra-5.1/cinelerra/overlayframe.inc | 113 +- cinelerra-5.1/cinelerra/overlaynearest.C | 195 ++ cinelerra-5.1/cinelerra/overlaysample.C | 288 +++ cinelerra-5.1/cinelerra/patchbay.C | 9 +- cinelerra-5.1/cinelerra/playback3d.C | 371 +--- cinelerra-5.1/cinelerra/preferencesthread.C | 2 +- cinelerra-5.1/cinelerra/theme.C | 9 +- cinelerra-5.1/cinelerra/vpatchgui.C | 133 +- cinelerra-5.1/cinelerra/vpatchgui.h | 22 + cinelerra-5.1/guicast/bcmenuitem.C | 7 + cinelerra-5.1/guicast/bcmenuitem.h | 1 + cinelerra-5.1/guicast/bcmenupopup.C | 8 +- cinelerra-5.1/guicast/bcwindowbase.C | 8 +- cinelerra-5.1/plugins/overlay/overlay.C | 243 +-- .../plugins/theme_blond/data/mode_and.png | Bin 0 -> 831 bytes .../plugins/theme_blond/data/mode_average.png | Bin 840 -> 0 bytes .../plugins/theme_blond/data/mode_burn.png | Bin 0 -> 743 bytes .../theme_blond/data/mode_difference.png | Bin 0 -> 276 bytes .../plugins/theme_blond/data/mode_dodge.png | Bin 0 -> 895 bytes .../theme_blond/data/mode_hardlight.png | Bin 0 -> 496 bytes .../plugins/theme_blond/data/mode_overlay.png | Bin 0 -> 784 bytes .../plugins/theme_blond/data/mode_screen.png | Bin 0 -> 719 bytes .../theme_blond/data/mode_softlight.png | Bin 0 -> 761 bytes .../plugins/theme_blond_cv/data/mode_and.png | Bin 0 -> 831 bytes .../theme_blond_cv/data/mode_average.png | Bin 840 -> 0 bytes .../plugins/theme_blond_cv/data/mode_burn.png | Bin 0 -> 743 bytes .../theme_blond_cv/data/mode_difference.png | Bin 0 -> 276 bytes .../theme_blond_cv/data/mode_dodge.png | Bin 0 -> 895 bytes .../theme_blond_cv/data/mode_hardlight.png | Bin 0 -> 496 bytes .../theme_blond_cv/data/mode_overlay.png | Bin 0 -> 784 bytes .../theme_blond_cv/data/mode_screen.png | Bin 0 -> 719 bytes .../theme_blond_cv/data/mode_softlight.png | Bin 0 -> 761 bytes .../plugins/theme_blue/data/mode_and.png | Bin 0 -> 831 bytes .../plugins/theme_blue/data/mode_average.png | Bin 840 -> 0 bytes .../plugins/theme_blue/data/mode_burn.png | Bin 0 -> 743 bytes .../theme_blue/data/mode_difference.png | Bin 0 -> 276 bytes .../plugins/theme_blue/data/mode_dodge.png | Bin 0 -> 895 bytes .../theme_blue/data/mode_hardlight.png | Bin 0 -> 496 bytes .../plugins/theme_blue/data/mode_overlay.png | Bin 0 -> 784 bytes .../plugins/theme_blue/data/mode_screen.png | Bin 0 -> 719 bytes .../theme_blue/data/mode_softlight.png | Bin 0 -> 761 bytes .../plugins/theme_blue_dot/data/mode_and.png | Bin 0 -> 831 bytes .../theme_blue_dot/data/mode_average.png | Bin 1028 -> 0 bytes .../plugins/theme_blue_dot/data/mode_burn.png | Bin 0 -> 743 bytes .../theme_blue_dot/data/mode_difference.png | Bin 0 -> 276 bytes .../theme_blue_dot/data/mode_dodge.png | Bin 0 -> 895 bytes .../theme_blue_dot/data/mode_hardlight.png | Bin 0 -> 496 bytes .../theme_blue_dot/data/mode_overlay.png | Bin 0 -> 784 bytes .../theme_blue_dot/data/mode_screen.png | Bin 0 -> 719 bytes .../theme_blue_dot/data/mode_softlight.png | Bin 0 -> 761 bytes .../plugins/theme_bright/data/mode_and.png | Bin 0 -> 831 bytes .../theme_bright/data/mode_average.png | Bin 840 -> 0 bytes .../plugins/theme_bright/data/mode_burn.png | Bin 0 -> 743 bytes .../theme_bright/data/mode_difference.png | Bin 0 -> 276 bytes .../plugins/theme_bright/data/mode_dodge.png | Bin 0 -> 895 bytes .../theme_bright/data/mode_hardlight.png | Bin 0 -> 496 bytes .../theme_bright/data/mode_overlay.png | Bin 0 -> 784 bytes .../plugins/theme_bright/data/mode_screen.png | Bin 0 -> 719 bytes .../theme_bright/data/mode_softlight.png | Bin 0 -> 761 bytes .../plugins/theme_hulk/data/mode_and.png | Bin 0 -> 831 bytes .../plugins/theme_hulk/data/mode_average.png | Bin 840 -> 0 bytes .../plugins/theme_hulk/data/mode_burn.png | Bin 0 -> 743 bytes .../theme_hulk/data/mode_difference.png | Bin 0 -> 276 bytes .../plugins/theme_hulk/data/mode_dodge.png | Bin 0 -> 895 bytes .../theme_hulk/data/mode_hardlight.png | Bin 0 -> 496 bytes .../plugins/theme_hulk/data/mode_overlay.png | Bin 0 -> 784 bytes .../plugins/theme_hulk/data/mode_screen.png | Bin 0 -> 719 bytes .../theme_hulk/data/mode_softlight.png | Bin 0 -> 761 bytes .../plugins/theme_pinklady/data/mode_and.png | Bin 0 -> 831 bytes .../theme_pinklady/data/mode_average.png | Bin 840 -> 0 bytes .../plugins/theme_pinklady/data/mode_burn.png | Bin 0 -> 743 bytes .../theme_pinklady/data/mode_difference.png | Bin 0 -> 276 bytes .../theme_pinklady/data/mode_dodge.png | Bin 0 -> 895 bytes .../theme_pinklady/data/mode_hardlight.png | Bin 0 -> 496 bytes .../theme_pinklady/data/mode_overlay.png | Bin 0 -> 784 bytes .../theme_pinklady/data/mode_screen.png | Bin 0 -> 719 bytes .../theme_pinklady/data/mode_softlight.png | Bin 0 -> 761 bytes .../plugins/theme_suv/data/mode_and.png | Bin 0 -> 831 bytes .../plugins/theme_suv/data/mode_average.png | Bin 840 -> 0 bytes .../plugins/theme_suv/data/mode_burn.png | Bin 0 -> 743 bytes .../theme_suv/data/mode_difference.png | Bin 0 -> 276 bytes .../plugins/theme_suv/data/mode_dodge.png | Bin 0 -> 895 bytes .../plugins/theme_suv/data/mode_hardlight.png | Bin 0 -> 496 bytes .../plugins/theme_suv/data/mode_overlay.png | Bin 0 -> 784 bytes .../plugins/theme_suv/data/mode_screen.png | Bin 0 -> 719 bytes .../plugins/theme_suv/data/mode_softlight.png | Bin 0 -> 761 bytes .../plugins/theme_unflat/data/mode_and.png | Bin 0 -> 831 bytes .../theme_unflat/data/mode_average.png | Bin 840 -> 0 bytes .../plugins/theme_unflat/data/mode_burn.png | Bin 0 -> 743 bytes .../theme_unflat/data/mode_difference.png | Bin 0 -> 276 bytes .../plugins/theme_unflat/data/mode_dodge.png | Bin 0 -> 895 bytes .../theme_unflat/data/mode_hardlight.png | Bin 0 -> 496 bytes .../theme_unflat/data/mode_overlay.png | Bin 0 -> 784 bytes .../plugins/theme_unflat/data/mode_screen.png | Bin 0 -> 719 bytes .../theme_unflat/data/mode_softlight.png | Bin 0 -> 761 bytes 107 files changed, 1340 insertions(+), 9928 deletions(-) create mode 100644 cinelerra-5.1/cinelerra/overlaydirect.C delete mode 100644 cinelerra-5.1/cinelerra/overlayframe.C.clamp delete mode 100644 cinelerra-5.1/cinelerra/overlayframe.C.float delete mode 100644 cinelerra-5.1/cinelerra/overlayframe.C.floattable delete mode 100644 cinelerra-5.1/cinelerra/overlayframe.C.int delete mode 100644 cinelerra-5.1/cinelerra/overlayframe.h.clamp delete mode 100644 cinelerra-5.1/cinelerra/overlayframe.h.float delete mode 100644 cinelerra-5.1/cinelerra/overlayframe.h.floattable delete mode 100644 cinelerra-5.1/cinelerra/overlayframe.h.int create mode 100644 cinelerra-5.1/cinelerra/overlaynearest.C create mode 100644 cinelerra-5.1/cinelerra/overlaysample.C create mode 100644 cinelerra-5.1/plugins/theme_blond/data/mode_and.png delete mode 100644 cinelerra-5.1/plugins/theme_blond/data/mode_average.png create mode 100644 cinelerra-5.1/plugins/theme_blond/data/mode_burn.png create mode 100644 cinelerra-5.1/plugins/theme_blond/data/mode_difference.png create mode 100644 cinelerra-5.1/plugins/theme_blond/data/mode_dodge.png create mode 100644 cinelerra-5.1/plugins/theme_blond/data/mode_hardlight.png create mode 100644 cinelerra-5.1/plugins/theme_blond/data/mode_overlay.png create mode 100644 cinelerra-5.1/plugins/theme_blond/data/mode_screen.png create mode 100644 cinelerra-5.1/plugins/theme_blond/data/mode_softlight.png create mode 100644 cinelerra-5.1/plugins/theme_blond_cv/data/mode_and.png delete mode 100644 cinelerra-5.1/plugins/theme_blond_cv/data/mode_average.png create mode 100644 cinelerra-5.1/plugins/theme_blond_cv/data/mode_burn.png create mode 100644 cinelerra-5.1/plugins/theme_blond_cv/data/mode_difference.png create mode 100644 cinelerra-5.1/plugins/theme_blond_cv/data/mode_dodge.png create mode 100644 cinelerra-5.1/plugins/theme_blond_cv/data/mode_hardlight.png create mode 100644 cinelerra-5.1/plugins/theme_blond_cv/data/mode_overlay.png create mode 100644 cinelerra-5.1/plugins/theme_blond_cv/data/mode_screen.png create mode 100644 cinelerra-5.1/plugins/theme_blond_cv/data/mode_softlight.png create mode 100644 cinelerra-5.1/plugins/theme_blue/data/mode_and.png delete mode 100644 cinelerra-5.1/plugins/theme_blue/data/mode_average.png create mode 100644 cinelerra-5.1/plugins/theme_blue/data/mode_burn.png create mode 100644 cinelerra-5.1/plugins/theme_blue/data/mode_difference.png create mode 100644 cinelerra-5.1/plugins/theme_blue/data/mode_dodge.png create mode 100644 cinelerra-5.1/plugins/theme_blue/data/mode_hardlight.png create mode 100644 cinelerra-5.1/plugins/theme_blue/data/mode_overlay.png create mode 100644 cinelerra-5.1/plugins/theme_blue/data/mode_screen.png create mode 100644 cinelerra-5.1/plugins/theme_blue/data/mode_softlight.png create mode 100644 cinelerra-5.1/plugins/theme_blue_dot/data/mode_and.png delete mode 100644 cinelerra-5.1/plugins/theme_blue_dot/data/mode_average.png create mode 100644 cinelerra-5.1/plugins/theme_blue_dot/data/mode_burn.png create mode 100644 cinelerra-5.1/plugins/theme_blue_dot/data/mode_difference.png create mode 100644 cinelerra-5.1/plugins/theme_blue_dot/data/mode_dodge.png create mode 100644 cinelerra-5.1/plugins/theme_blue_dot/data/mode_hardlight.png create mode 100644 cinelerra-5.1/plugins/theme_blue_dot/data/mode_overlay.png create mode 100644 cinelerra-5.1/plugins/theme_blue_dot/data/mode_screen.png create mode 100644 cinelerra-5.1/plugins/theme_blue_dot/data/mode_softlight.png create mode 100644 cinelerra-5.1/plugins/theme_bright/data/mode_and.png delete mode 100644 cinelerra-5.1/plugins/theme_bright/data/mode_average.png create mode 100644 cinelerra-5.1/plugins/theme_bright/data/mode_burn.png create mode 100644 cinelerra-5.1/plugins/theme_bright/data/mode_difference.png create mode 100644 cinelerra-5.1/plugins/theme_bright/data/mode_dodge.png create mode 100644 cinelerra-5.1/plugins/theme_bright/data/mode_hardlight.png create mode 100644 cinelerra-5.1/plugins/theme_bright/data/mode_overlay.png create mode 100644 cinelerra-5.1/plugins/theme_bright/data/mode_screen.png create mode 100644 cinelerra-5.1/plugins/theme_bright/data/mode_softlight.png create mode 100644 cinelerra-5.1/plugins/theme_hulk/data/mode_and.png delete mode 100644 cinelerra-5.1/plugins/theme_hulk/data/mode_average.png create mode 100644 cinelerra-5.1/plugins/theme_hulk/data/mode_burn.png create mode 100644 cinelerra-5.1/plugins/theme_hulk/data/mode_difference.png create mode 100644 cinelerra-5.1/plugins/theme_hulk/data/mode_dodge.png create mode 100644 cinelerra-5.1/plugins/theme_hulk/data/mode_hardlight.png create mode 100644 cinelerra-5.1/plugins/theme_hulk/data/mode_overlay.png create mode 100644 cinelerra-5.1/plugins/theme_hulk/data/mode_screen.png create mode 100644 cinelerra-5.1/plugins/theme_hulk/data/mode_softlight.png create mode 100644 cinelerra-5.1/plugins/theme_pinklady/data/mode_and.png delete mode 100644 cinelerra-5.1/plugins/theme_pinklady/data/mode_average.png create mode 100644 cinelerra-5.1/plugins/theme_pinklady/data/mode_burn.png create mode 100644 cinelerra-5.1/plugins/theme_pinklady/data/mode_difference.png create mode 100644 cinelerra-5.1/plugins/theme_pinklady/data/mode_dodge.png create mode 100644 cinelerra-5.1/plugins/theme_pinklady/data/mode_hardlight.png create mode 100644 cinelerra-5.1/plugins/theme_pinklady/data/mode_overlay.png create mode 100644 cinelerra-5.1/plugins/theme_pinklady/data/mode_screen.png create mode 100644 cinelerra-5.1/plugins/theme_pinklady/data/mode_softlight.png create mode 100644 cinelerra-5.1/plugins/theme_suv/data/mode_and.png delete mode 100644 cinelerra-5.1/plugins/theme_suv/data/mode_average.png create mode 100644 cinelerra-5.1/plugins/theme_suv/data/mode_burn.png create mode 100644 cinelerra-5.1/plugins/theme_suv/data/mode_difference.png create mode 100644 cinelerra-5.1/plugins/theme_suv/data/mode_dodge.png create mode 100644 cinelerra-5.1/plugins/theme_suv/data/mode_hardlight.png create mode 100644 cinelerra-5.1/plugins/theme_suv/data/mode_overlay.png create mode 100644 cinelerra-5.1/plugins/theme_suv/data/mode_screen.png create mode 100644 cinelerra-5.1/plugins/theme_suv/data/mode_softlight.png create mode 100644 cinelerra-5.1/plugins/theme_unflat/data/mode_and.png delete mode 100644 cinelerra-5.1/plugins/theme_unflat/data/mode_average.png create mode 100644 cinelerra-5.1/plugins/theme_unflat/data/mode_burn.png create mode 100644 cinelerra-5.1/plugins/theme_unflat/data/mode_difference.png create mode 100644 cinelerra-5.1/plugins/theme_unflat/data/mode_dodge.png create mode 100644 cinelerra-5.1/plugins/theme_unflat/data/mode_hardlight.png create mode 100644 cinelerra-5.1/plugins/theme_unflat/data/mode_overlay.png create mode 100644 cinelerra-5.1/plugins/theme_unflat/data/mode_screen.png create mode 100644 cinelerra-5.1/plugins/theme_unflat/data/mode_softlight.png diff --git a/cinelerra-5.1/cinelerra/Makefile b/cinelerra-5.1/cinelerra/Makefile index f2c3debd..853ab8f1 100644 --- a/cinelerra-5.1/cinelerra/Makefile +++ b/cinelerra-5.1/cinelerra/Makefile @@ -191,7 +191,10 @@ OBJS = \ $(OBJDIR)/nestededls.o \ $(OBJDIR)/newfolder.o \ $(OBJDIR)/new.o \ + $(OBJDIR)/overlaydirect.o \ $(OBJDIR)/overlayframe.o \ + $(OBJDIR)/overlaynearest.o \ + $(OBJDIR)/overlaysample.o \ $(OBJDIR)/packagedispatcher.o \ $(OBJDIR)/packagerenderer.o \ $(OBJDIR)/packagingengine.o \ diff --git a/cinelerra-5.1/cinelerra/overlaydirect.C b/cinelerra-5.1/cinelerra/overlaydirect.C new file mode 100644 index 00000000..3297fda3 --- /dev/null +++ b/cinelerra-5.1/cinelerra/overlaydirect.C @@ -0,0 +1,122 @@ +#include "overlayframe.h" + +/* Direct translate / blend **********************************************/ + +#define XBLEND(FN, temp_type, type, max, components, ofs, round) { \ + temp_type opcty = fade * max + round, trnsp = max - opcty; \ + type** output_rows = (type**)output->get_rows(); \ + type** input_rows = (type**)input->get_rows(); \ + ix *= components; ox *= components; \ + \ + for(int i = pkg->out_row1; i < pkg->out_row2; i++) { \ + type* in_row = input_rows[i + iy] + ix; \ + type* output = output_rows[i] + ox; \ + for(int j = 0; j < ow; j++) { \ + if( components == 4 ) { \ + temp_type r, g, b, a; \ + ALPHA4_BLEND(FN, temp_type, in_row, output, max, ofs, ofs, round); \ + ALPHA4_STORE(output, ofs, max); \ + } \ + else { \ + temp_type r, g, b; \ + ALPHA3_BLEND(FN, temp_type, in_row, output, max, ofs, ofs, round); \ + ALPHA3_STORE(output, ofs, max); \ + } \ + in_row += components; output += components; \ + } \ + } \ + break; \ +} + +#define XBLEND_ONLY(FN) { \ + switch(input->get_color_model()) { \ + case BC_RGB_FLOAT: XBLEND(FN, z_float, z_float, 1.f, 3, 0, 0.f); \ + case BC_RGBA_FLOAT: XBLEND(FN, z_float, z_float, 1.f, 4, 0, 0.f); \ + case BC_RGB888: XBLEND(FN, z_int32_t, z_uint8_t, 0xff, 3, 0, .5f); \ + case BC_YUV888: XBLEND(FN, z_int32_t, z_uint8_t, 0xff, 3, 0x80, .5f); \ + case BC_RGBA8888: XBLEND(FN, z_int32_t, z_uint8_t, 0xff, 4, 0, .5f); \ + case BC_YUVA8888: XBLEND(FN, z_int32_t, z_uint8_t, 0xff, 4, 0x80, .5f); \ + case BC_RGB161616: XBLEND(FN, z_int64_t, z_uint16_t, 0xffff, 3, 0, .5f); \ + case BC_YUV161616: XBLEND(FN, z_int64_t, z_uint16_t, 0xffff, 3, 0x8000, .5f); \ + case BC_RGBA16161616: XBLEND(FN, z_int64_t, z_uint16_t, 0xffff, 4, 0, .5f); \ + case BC_YUVA16161616: XBLEND(FN, z_int64_t, z_uint16_t, 0xffff, 4, 0x8000, .5f); \ + } \ + break; \ +} + +DirectPackage::DirectPackage() +{ +} + +DirectUnit::DirectUnit(DirectEngine *server) + : LoadClient(server) +{ + this->engine = server; +} + +DirectUnit::~DirectUnit() +{ +} + +void DirectUnit::process_package(LoadPackage *package) +{ + DirectPackage *pkg = (DirectPackage*)package; + + VFrame *output = engine->output; + VFrame *input = engine->input; + int mode = engine->mode; + float fade = + BC_CModels::has_alpha(input->get_color_model()) && + mode == TRANSFER_REPLACE ? 1.f : engine->alpha; + + int ix = engine->in_x1; + int ox = engine->out_x1; + int ow = engine->out_x2 - ox; + int iy = engine->in_y1 - engine->out_y1; + + BLEND_SWITCH(XBLEND_ONLY); +} + +DirectEngine::DirectEngine(int cpus) + : LoadServer(cpus, cpus) +{ +} + +DirectEngine::~DirectEngine() +{ +} + +void DirectEngine::init_packages() +{ + if(in_x1 < 0) { out_x1 -= in_x1; in_x1 = 0; } + if(in_y1 < 0) { out_y1 -= in_y1; in_y1 = 0; } + if(out_x1 < 0) { in_x1 -= out_x1; out_x1 = 0; } + if(out_y1 < 0) { in_y1 -= out_y1; out_y1 = 0; } + if(out_x2 > output->get_w()) out_x2 = output->get_w(); + if(out_y2 > output->get_h()) out_y2 = output->get_h(); + int out_w = out_x2 - out_x1; + int out_h = out_y2 - out_y1; + if( !out_w || !out_h ) return; + + int rows = out_h; + int pkgs = get_total_packages(); + int row1 = out_y1, row2 = row1; + for(int i = 0; i < pkgs; row1=row2 ) { + DirectPackage *package = (DirectPackage*)get_package(i); + row2 = ++i * rows / pkgs + out_y1; + package->out_row1 = row1; + package->out_row2 = row2; + } +} + +LoadClient* DirectEngine::new_client() +{ + return new DirectUnit(this); +} + +LoadPackage* DirectEngine::new_package() +{ + return new DirectPackage; +} + + diff --git a/cinelerra-5.1/cinelerra/overlayframe.C b/cinelerra-5.1/cinelerra/overlayframe.C index 642a9367..849912fd 100644 --- a/cinelerra-5.1/cinelerra/overlayframe.C +++ b/cinelerra-5.1/cinelerra/overlayframe.C @@ -20,54 +20,11 @@ * */ -#include -#include -#include -#include -#include -#include - #include "clip.h" #include "edl.inc" #include "mutex.h" #include "overlayframe.h" #include "units.h" -#include "vframe.h" - -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); } - -static inline int32_t aclip(int32_t v, int mx) { - return v < 0 ? 0 : v > mx ? mx : v; -} -static inline int64_t aclip(int64_t v, int mx) { - return v < 0 ? 0 : v > mx ? mx : v; -} -static inline float aclip(float v, float mx) { - return v < 0 ? 0 : v > mx ? mx : v; -} -static inline float aclip(float v, int mx) { - return v < 0 ? 0 : v > mx ? mx : v; -} -static inline int aclip(int v, float mx) { - return v < 0 ? 0 : v > mx ? mx : v; -} -static inline int32_t cclip(int32_t v, int mx) { - return v > (mx/=2) ? mx : v < (mx=(-mx-1)) ? mx : v; -} -static inline int64_t cclip(int64_t v, int mx) { - return v > (mx/=2) ? mx : v < (mx=(-mx-1)) ? mx : v; -} -static inline float cclip(float v, float mx) { - return v > (mx/=2) ? mx : v < (mx=(-mx)) ? mx : v; -} -static inline float cclip(float v, int mx) { - return v > (mx/=2) ? mx : v < (mx=(-mx-1)) ? mx : v; -} -static inline int cclip(int v, float mx) { - return v > (mx/=2) ? mx : v < (mx=(-mx-1)) ? mx : v; -} /* * New resampler code; replace the original somehwat blurry engine @@ -107,19 +64,11 @@ static inline int cclip(int v, float mx) { * output_alpha = output_alpha + ((max - output_alpha) * input_alpha) / max; */ -#define TRANSFORM_SPP (4096) /* number of data pts per unit x in lookup table */ -#define INDEX_FRACTION (8) /* bits of fraction past TRANSFORM_SPP on kernel - index accumulation */ -#define TRANSFORM_MIN (.5 / TRANSFORM_SPP) - /* Sinc needed for Lanczos kernel */ static float sinc(const float x) { + if(fabsf(x) < TRANSFORM_MIN) return 1.0f; float y = x * M_PI; - - if(fabsf(x) < TRANSFORM_MIN) - return 1.0f; - return sinf(y) / y; } @@ -405,852 +354,4 @@ int OverlayFrame::overlay(VFrame *output, VFrame *input, return 0; } -// 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) -#define CHROMA_NORMAL COLOR_NORMAL - -// ADDITION [(Sa + Da), (Sc + Dc)] -#define ALPHA_ADDITION(mx, Sa, Da) (Sa + Da) -#define COLOR_ADDITION(mx, Sc, Sa, Dc, Da) (Sc + Dc) -#define CHROMA_ADDITION(mx, Sc, Sa, Dc, Da) (Sc + Dc) - -// SUBTRACT [(Sa - Da), (Sc - Dc)] -#define ALPHA_SUBTRACT(mx, Sa, Da) (Sa - Da) -#define COLOR_SUBTRACT(mx, Sc, Sa, Dc, Da) (Sc - Dc) -#define CHROMA_SUBTRACT(mx, Sc, Sa, Dc, Da) (Sc - Dc) - -// MULTIPLY [(Sa * Da), Sc * Dc] -#define ALPHA_MULTIPLY(mx, Sa, Da) ((Sa * Da) / mx) -#define COLOR_MULTIPLY(mx, Sc, Sa, Dc, Da) ((Sc * Dc) / mx) -#define CHROMA_MULTIPLY(mx, Sc, Sa, Dc, Da) ((Sc * Dc) / mx) - -// DIVIDE [(Sa / Da), (Sc / Dc)] -#define ALPHA_DIVIDE(mx, Sa, Da) (Da ? ((Sa * mx) / Da) : mx) -#define COLOR_DIVIDE(mx, Sc, Sa, Dc, Da) (Dc ? ((Sc * mx) / Dc) : mx) -#define CHROMA_DIVIDE(mx, Sc, Sa, Dc, Da) (Dc ? ((Sc * mx) / Dc) : mx) - -// REPLACE [Sa, Sc] (fade = 1) -#define ALPHA_REPLACE(mx, Sa, Da) Sa -#define COLOR_REPLACE(mx, Sc, Sa, Dc, Da) Sc -#define CHROMA_REPLACE COLOR_REPLACE - -// MAX [max(Sa, Da), MAX(Sc, Dc)] -#define ALPHA_MAX(mx, Sa, Da) (Sa > Da ? Sa : Da) -#define COLOR_MAX(mx, Sc, Sa, Dc, Da) (Sc > Dc ? Sc : Dc) -#define CHROMA_MAX(mx, Sc, Sa, Dc, Da) (mabs(Sc) > mabs(Dc) ? Sc : Dc) - -// MIN [min(Sa, Da), MIN(Sc, Dc)] -#define ALPHA_MIN(mx, Sa, Da) (Sa < Da ? Sa : Da) -#define COLOR_MIN(mx, Sc, Sa, Dc, Da) (Sc < Dc ? Sc : Dc) -#define CHROMA_MIN(mx, Sc, Sa, Dc, Da) (mabs(Sc) < mabs(Dc) ? Sc : Dc) - -// AVERAGE [(Sa + Da) * 0.5, (Sc + Dc) * 0.5] -#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 - -// DARKEN [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] -#define ALPHA_DARKEN(mx, Sa, Da) (Sa + Da - (Sa * Da) / mx) -#define COLOR_DARKEN(mx, Sc, Sa, Dc, Da) ((Sc * (mx - Da) + Dc * (mx - Sa)) / mx + (Sc < Dc ? Sc : Dc)) -#define CHROMA_DARKEN(mx, Sc, Sa, Dc, Da) ((Sc * (mx - Da) + Dc * (mx - Sa)) / mx + (mabs(Sc) < mabs(Dc) ? Sc : Dc)) - -// LIGHTEN [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] -#define ALPHA_LIGHTEN(mx, Sa, Da) (Sa + Da - Sa * Da / mx) -#define COLOR_LIGHTEN(mx, Sc, Sa, Dc, Da) ((Sc * (mx - Da) + Dc * (mx - Sa)) / mx + (Sc > Dc ? Sc : Dc)) -#define CHROMA_LIGHTEN(mx, Sc, Sa, Dc, Da) ((Sc * (mx - Da) + Dc * (mx - Sa)) / mx + (mabs(Sc) > mabs(Dc) ? Sc : Dc)) - -// DST [Da, Dc] -#define ALPHA_DST(mx, Sa, Da) Da -#define COLOR_DST(mx, Sc, Sa, Dc, Da) Dc -#define CHROMA_DST COLOR_DST - -// DST_ATOP [Sa, Sc * (1 - Da) + Dc * Sa] -#define ALPHA_DST_ATOP(mx, Sa, Da) Sa -#define COLOR_DST_ATOP(mx, Sc, Sa, Dc, Da) ((Sc * (mx - Da) + Dc * Sa) / mx) -#define CHROMA_DST_ATOP COLOR_DST_ATOP - -// DST_IN [Da * Sa, Dc * Sa] -#define ALPHA_DST_IN(mx, Sa, Da) ((Da * Sa) / mx) -#define COLOR_DST_IN(mx, Sc, Sa, Dc, Da) ((Dc * Sa) / mx) -#define CHROMA_DST_IN COLOR_DST_IN - -// DST_OUT [Da * (1 - Sa), Dc * (1 - Sa)] -#define ALPHA_DST_OUT(mx, Sa, Da) (Da * (mx - Sa) / mx) -#define COLOR_DST_OUT(mx, Sc, Sa, Dc, Da) (Dc * (mx - Sa) / mx) -#define CHROMA_DST_OUT COLOR_DST_OUT - -// DST_OVER [Sa * (1 - Da) + Da, Sc * (1 - Da) + Dc] -#define ALPHA_DST_OVER(mx, Sa, Da) ((Sa * (mx - Da)) / mx + Da) -#define COLOR_DST_OVER(mx, Sc, Sa, Dc, Da) (Sc * (mx - Da)/ mx + Dc) -#define CHROMA_DST_OVER COLOR_DST_OVER - -// SRC [Sa, Sc] -#define ALPHA_SRC(mx, Sa, Da) Sa -#define COLOR_SRC(mx, Sc, Sa, Dc, Da) Sc -#define CHROMA_SRC COLOR_SRC - -// SRC_ATOP [Da, Sc * Da + Dc * (1 - Sa)] -#define ALPHA_SRC_ATOP(mx, Sa, Da) Da -#define COLOR_SRC_ATOP(mx, Sc, Sa, Dc, Da) ((Sc * Da + Dc * (mx - Sa)) / mx) -#define CHROMA_SRC_ATOP COLOR_SRC_ATOP - -// SRC_IN [Sa * Da, Sc * Da] -#define ALPHA_SRC_IN(mx, Sa, Da) ((Sa * Da) / mx) -#define COLOR_SRC_IN(mx, Sc, Sa, Dc, Da) (Sc * Da / mx) -#define CHROMA_SRC_IN COLOR_SRC_IN - -// SRC_OUT [Sa * (1 - Da), Sc * (1 - Da)] -#define ALPHA_SRC_OUT(mx, Sa, Da) (Sa * (mx - Da) / mx) -#define COLOR_SRC_OUT(mx, Sc, Sa, Dc, Da) (Sc * (mx - Da) / mx) -#define CHROMA_SRC_OUT COLOR_SRC_OUT - -// SRC_OVER [Sa + Da * (1 - Sa), Sc + (1 - Sa) * Dc] -#define ALPHA_SRC_OVER(mx, Sa, Da) (Sa + Da * (mx - Sa) / mx) -#define COLOR_SRC_OVER(mx, Sc, Sa, Dc, Da) (Sc + Dc * (mx - Sa) / mx) -#define CHROMA_SRC_OVER COLOR_SRC_OVER - -// OR [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -#define ALPHA_OR(mx, Sa, Da) (Sa + Da - (Sa * Da) / mx) -#define COLOR_OR(mx, Sc, Sa, Dc, Da) (Sc + Dc - (Sc * Dc) / mx) -#define CHROMA_OR COLOR_OR - -// XOR [Sa * (1 - Da) + Da * (1 - Sa), Sc * (1 - Da) + Dc * (1 - Sa)] -#define ALPHA_XOR(mx, Sa, Da) ((Sa * (mx - Da) + Da * (mx - Sa)) / mx) -#define COLOR_XOR(mx, Sc, Sa, Dc, Da) ((Sc * (mx - Da) + Dc * (mx - Sa)) / mx) -#define CHROMA_XOR COLOR_XOR - -#define ZTYP(ty) typedef ty z_##ty __attribute__ ((__unused__)) -ZTYP(int8_t); ZTYP(uint8_t); -ZTYP(int16_t); ZTYP(uint16_t); -ZTYP(int32_t); ZTYP(uint32_t); -ZTYP(int64_t); ZTYP(uint64_t); -ZTYP(float); ZTYP(double); - -#define ALPHA3_BLEND(FN, typ, inp, out, mx, iofs, oofs, rnd) \ - typ inp0 = (typ)inp[0], inp1 = (typ)inp[1] - iofs; \ - typ inp2 = (typ)inp[2] - iofs, inp3 = mx; \ - typ out0 = (typ)out[0], out1 = (typ)out[1] - oofs; \ - typ out2 = (typ)out[2] - oofs, out3 = mx; \ - r = COLOR_##FN(mx, inp0, inp3, out0, out3); \ - if( oofs ) { \ - g = CHROMA_##FN(mx, inp1, inp3, out1, out3); \ - b = CHROMA_##FN(mx, inp2, inp3, out2, out3); \ - } \ - else { \ - g = COLOR_##FN(mx, inp1, inp3, out1, out3); \ - b = COLOR_##FN(mx, inp2, inp3, out2, out3); \ - } - -#define ALPHA4_BLEND(FN, typ, inp, out, mx, iofs, oofs, rnd) \ - typ inp0 = (typ)inp[0], inp1 = (typ)inp[1] - iofs; \ - typ inp2 = (typ)inp[2] - iofs, inp3 = inp[3]; \ - typ out0 = (typ)out[0], out1 = (typ)out[1] - oofs; \ - typ out2 = (typ)out[2] - oofs, out3 = out[3]; \ - r = COLOR_##FN(mx, inp0, inp3, out0, out3); \ - if( oofs ) { \ - g = CHROMA_##FN(mx, inp1, inp3, out1, out3); \ - b = CHROMA_##FN(mx, inp2, inp3, out2, out3); \ - } \ - else { \ - g = COLOR_##FN(mx, inp1, inp3, out1, out3); \ - b = COLOR_##FN(mx, inp2, inp3, out2, out3); \ - } \ - a = ALPHA_##FN(mx, inp3, out3) - -#define ALPHA_STORE(out, ofs, mx) \ - out[0] = r; \ - out[1] = g + ofs; \ - out[2] = b + ofs - -#define ALPHA3_STORE(out, ofs, mx) \ - r = aclip(r, mx); \ - g = ofs ? cclip(g, mx) : aclip(g, mx); \ - b = ofs ? cclip(b, mx) : aclip(b, mx); \ - if( trnsp ) { \ - r = (r * opcty + out0 * trnsp) / mx; \ - g = (g * opcty + out1 * trnsp) / mx; \ - b = (b * opcty + out2 * trnsp) / mx; \ - } \ - ALPHA_STORE(out, ofs, mx) - -#define ALPHA4_STORE(out, ofs, mx) \ - r = aclip(r, mx); \ - g = ofs ? cclip(g, mx) : aclip(g, mx); \ - b = ofs ? cclip(b, mx) : aclip(b, mx); \ - if( trnsp ) { \ - r = (r * opcty + out0 * trnsp) / mx; \ - g = (g * opcty + out1 * trnsp) / mx; \ - b = (b * opcty + out2 * trnsp) / mx; \ - a = (a * opcty + out3 * trnsp) / mx; \ - } \ - ALPHA_STORE(out, ofs, mx); \ - out[3] = aclip(a, mx) - -#define XBLEND(FN, temp_type, type, max, components, ofs, round) { \ - temp_type opcty = fade * max + round, trnsp = max - opcty; \ - type** output_rows = (type**)output->get_rows(); \ - type** input_rows = (type**)input->get_rows(); \ - ix *= components; ox *= components; \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) { \ - type* in_row = input_rows[i + iy] + ix; \ - type* output = output_rows[i] + ox; \ - for(int j = 0; j < ow; j++) { \ - if( components == 4 ) { \ - temp_type r, g, b, a; \ - ALPHA4_BLEND(FN, temp_type, in_row, output, max, ofs, ofs, round); \ - ALPHA4_STORE(output, ofs, max); \ - } \ - else { \ - temp_type r, g, b; \ - ALPHA3_BLEND(FN, temp_type, in_row, output, max, ofs, ofs, round); \ - ALPHA3_STORE(output, ofs, max); \ - } \ - in_row += components; output += components; \ - } \ - } \ - break; \ -} - -#define XBLEND_ONLY(FN) { \ - switch(input->get_color_model()) { \ - case BC_RGB_FLOAT: XBLEND(FN, z_float, z_float, 1.f, 3, 0, 0.f); \ - case BC_RGBA_FLOAT: XBLEND(FN, z_float, z_float, 1.f, 4, 0, 0.f); \ - case BC_RGB888: XBLEND(FN, z_int32_t, z_uint8_t, 0xff, 3, 0, .5f); \ - case BC_YUV888: XBLEND(FN, z_int32_t, z_uint8_t, 0xff, 3, 0x80, .5f); \ - case BC_RGBA8888: XBLEND(FN, z_int32_t, z_uint8_t, 0xff, 4, 0, .5f); \ - case BC_YUVA8888: XBLEND(FN, z_int32_t, z_uint8_t, 0xff, 4, 0x80, .5f); \ - case BC_RGB161616: XBLEND(FN, z_int64_t, z_uint16_t, 0xffff, 3, 0, .5f); \ - case BC_YUV161616: XBLEND(FN, z_int64_t, z_uint16_t, 0xffff, 3, 0x8000, .5f); \ - case BC_RGBA16161616: XBLEND(FN, z_int64_t, z_uint16_t, 0xffff, 4, 0, .5f); \ - case BC_YUVA16161616: XBLEND(FN, z_int64_t, z_uint16_t, 0xffff, 4, 0x8000, .5f); \ - } \ - break; \ -} - -/* Direct translate / blend **********************************************/ - -DirectPackage::DirectPackage() -{ -} - -DirectUnit::DirectUnit(DirectEngine *server) - : LoadClient(server) -{ - this->engine = server; -} - -DirectUnit::~DirectUnit() -{ -} - -void DirectUnit::process_package(LoadPackage *package) -{ - DirectPackage *pkg = (DirectPackage*)package; - - VFrame *output = engine->output; - VFrame *input = engine->input; - int mode = engine->mode; - float fade = - BC_CModels::has_alpha(input->get_color_model()) && - mode == TRANSFER_REPLACE ? 1.f : engine->alpha; - - int ix = engine->in_x1; - int ox = engine->out_x1; - int ow = engine->out_x2 - ox; - int iy = engine->in_y1 - engine->out_y1; - - switch( mode ) { - case TRANSFER_NORMAL: XBLEND_ONLY(NORMAL); - case TRANSFER_ADDITION: XBLEND_ONLY(ADDITION); - case TRANSFER_SUBTRACT: XBLEND_ONLY(SUBTRACT); - case TRANSFER_MULTIPLY: XBLEND_ONLY(MULTIPLY); - case TRANSFER_DIVIDE: XBLEND_ONLY(DIVIDE); - case TRANSFER_REPLACE: XBLEND_ONLY(REPLACE); - case TRANSFER_MAX: XBLEND_ONLY(MAX); - case TRANSFER_MIN: XBLEND_ONLY(MIN); - case TRANSFER_AVERAGE: XBLEND_ONLY(AVERAGE); - case TRANSFER_DARKEN: XBLEND_ONLY(DARKEN); - case TRANSFER_LIGHTEN: XBLEND_ONLY(LIGHTEN); - case TRANSFER_DST: XBLEND_ONLY(DST); - case TRANSFER_DST_ATOP: XBLEND_ONLY(DST_ATOP); - case TRANSFER_DST_IN: XBLEND_ONLY(DST_IN); - case TRANSFER_DST_OUT: XBLEND_ONLY(DST_OUT); - case TRANSFER_DST_OVER: XBLEND_ONLY(DST_OVER); - case TRANSFER_SRC: XBLEND_ONLY(SRC); - case TRANSFER_SRC_ATOP: XBLEND_ONLY(SRC_ATOP); - case TRANSFER_SRC_IN: XBLEND_ONLY(SRC_IN); - case TRANSFER_SRC_OUT: XBLEND_ONLY(SRC_OUT); - case TRANSFER_SRC_OVER: XBLEND_ONLY(SRC_OVER); - case TRANSFER_OR: XBLEND_ONLY(OR); - case TRANSFER_XOR: XBLEND_ONLY(XOR); - } -} - -DirectEngine::DirectEngine(int cpus) - : LoadServer(cpus, cpus) -{ -} - -DirectEngine::~DirectEngine() -{ -} - -void DirectEngine::init_packages() -{ - if(in_x1 < 0) { out_x1 -= in_x1; in_x1 = 0; } - if(in_y1 < 0) { out_y1 -= in_y1; in_y1 = 0; } - if(out_x1 < 0) { in_x1 -= out_x1; out_x1 = 0; } - if(out_y1 < 0) { in_y1 -= out_y1; out_y1 = 0; } - if(out_x2 > output->get_w()) out_x2 = output->get_w(); - if(out_y2 > output->get_h()) out_y2 = output->get_h(); - int out_w = out_x2 - out_x1; - int out_h = out_y2 - out_y1; - if( !out_w || !out_h ) return; - - int rows = out_h; - int pkgs = get_total_packages(); - int row1 = out_y1, row2 = row1; - for(int i = 0; i < pkgs; row1=row2 ) { - DirectPackage *package = (DirectPackage*)get_package(i); - row2 = ++i * rows / pkgs + out_y1; - package->out_row1 = row1; - package->out_row2 = row2; - } -} - -LoadClient* DirectEngine::new_client() -{ - return new DirectUnit(this); -} - -LoadPackage* DirectEngine::new_package() -{ - return new DirectPackage; -} - -/* Nearest Neighbor scale / translate / blend ********************/ - -#define XBLEND_3NN(FN, temp_type, type, max, components, ofs, round) { \ - temp_type opcty = fade * max + round, trnsp = max - opcty; \ - type** output_rows = (type**)output->get_rows(); \ - type** input_rows = (type**)input->get_rows(); \ - ox *= components; \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) { \ - int *lx = engine->in_lookup_x; \ - type* in_row = input_rows[*ly++]; \ - type* output = output_rows[i] + ox; \ - for(int j = 0; j < ow; j++) { \ - in_row += *lx++; \ - if( components == 4 ) { \ - temp_type r, g, b, a; \ - ALPHA4_BLEND(FN, temp_type, in_row, output, max, ofs, ofs, round); \ - ALPHA4_STORE(output, ofs, max); \ - } \ - else { \ - temp_type r, g, b; \ - ALPHA3_BLEND(FN, temp_type, in_row, output, max, ofs, ofs, round); \ - ALPHA3_STORE(output, ofs, max); \ - } \ - output += components; \ - } \ - } \ - break; \ -} - -#define XBLEND_NN(FN) { \ - switch(input->get_color_model()) { \ - case BC_RGB_FLOAT: XBLEND_3NN(FN, z_float, z_float, 1.f, 3, 0, 0.f); \ - case BC_RGBA_FLOAT: XBLEND_3NN(FN, z_float, z_float, 1.f, 4, 0, 0.f); \ - case BC_RGB888: XBLEND_3NN(FN, z_int32_t, z_uint8_t, 0xff, 3, 0, .5f); \ - case BC_YUV888: XBLEND_3NN(FN, z_int32_t, z_uint8_t, 0xff, 3, 0x80, .5f); \ - case BC_RGBA8888: XBLEND_3NN(FN, z_int32_t, z_uint8_t, 0xff, 4, 0, .5f); \ - case BC_YUVA8888: XBLEND_3NN(FN, z_int32_t, z_uint8_t, 0xff, 4, 0x80, .5f); \ - case BC_RGB161616: XBLEND_3NN(FN, z_int64_t, z_uint16_t, 0xffff, 3, 0, .5f); \ - case BC_YUV161616: XBLEND_3NN(FN, z_int64_t, z_uint16_t, 0xffff, 3, 0x8000, .5f); \ - case BC_RGBA16161616: XBLEND_3NN(FN, z_int64_t, z_uint16_t, 0xffff, 4, 0, .5f); \ - case BC_YUVA16161616: XBLEND_3NN(FN, z_int64_t, z_uint16_t, 0xffff, 4, 0x8000, .5f); \ - } \ - break; \ -} - -NNPackage::NNPackage() -{ -} - -NNUnit::NNUnit(NNEngine *server) - : LoadClient(server) -{ - this->engine = server; -} - -NNUnit::~NNUnit() -{ -} - -void NNUnit::process_package(LoadPackage *package) -{ - NNPackage *pkg = (NNPackage*)package; - VFrame *output = engine->output; - VFrame *input = engine->input; - int mode = engine->mode; - float fade = - BC_CModels::has_alpha(input->get_color_model()) && - mode == TRANSFER_REPLACE ? 1.f : engine->alpha; - int ox = engine->out_x1i; - int ow = engine->out_x2i - ox; - int *ly = engine->in_lookup_y + pkg->out_row1; - - switch( mode ) { - case TRANSFER_NORMAL: XBLEND_NN(NORMAL); - case TRANSFER_ADDITION: XBLEND_NN(ADDITION); - case TRANSFER_SUBTRACT: XBLEND_NN(SUBTRACT); - case TRANSFER_MULTIPLY: XBLEND_NN(MULTIPLY); - case TRANSFER_DIVIDE: XBLEND_NN(DIVIDE); - case TRANSFER_REPLACE: XBLEND_NN(REPLACE); - case TRANSFER_MAX: XBLEND_NN(MAX); - case TRANSFER_MIN: XBLEND_NN(MIN); - case TRANSFER_AVERAGE: XBLEND_NN(AVERAGE); - case TRANSFER_DARKEN: XBLEND_NN(DARKEN); - case TRANSFER_LIGHTEN: XBLEND_NN(LIGHTEN); - case TRANSFER_DST: XBLEND_NN(DST); - case TRANSFER_DST_ATOP: XBLEND_NN(DST_ATOP); - case TRANSFER_DST_IN: XBLEND_NN(DST_IN); - case TRANSFER_DST_OUT: XBLEND_NN(DST_OUT); - case TRANSFER_DST_OVER: XBLEND_NN(DST_OVER); - case TRANSFER_SRC: XBLEND_NN(SRC); - case TRANSFER_SRC_ATOP: XBLEND_NN(SRC_ATOP); - case TRANSFER_SRC_IN: XBLEND_NN(SRC_IN); - case TRANSFER_SRC_OUT: XBLEND_NN(SRC_OUT); - case TRANSFER_SRC_OVER: XBLEND_NN(SRC_OVER); - case TRANSFER_OR: XBLEND_NN(OR); - case TRANSFER_XOR: XBLEND_NN(XOR); - } -} - -NNEngine::NNEngine(int cpus) - : LoadServer(cpus, cpus) -{ - in_lookup_x = 0; - in_lookup_y = 0; -} - -NNEngine::~NNEngine() -{ - if(in_lookup_x) - delete[] in_lookup_x; - if(in_lookup_y) - delete[] in_lookup_y; -} - -void NNEngine::init_packages() -{ - int in_w = input->get_w(); - int in_h = input->get_h(); - int out_w = output->get_w(); - int out_h = output->get_h(); - - float in_subw = in_x2 - in_x1; - float in_subh = in_y2 - in_y1; - float out_subw = out_x2 - out_x1; - float out_subh = out_y2 - out_y1; - int first, last, count, i; - int components = 3; - - out_x1i = rint(out_x1); - out_x2i = rint(out_x2); - if(out_x1i < 0) out_x1i = 0; - if(out_x1i > out_w) out_x1i = out_w; - if(out_x2i < 0) out_x2i = 0; - if(out_x2i > out_w) out_x2i = out_w; - int out_wi = out_x2i - out_x1i; - if( !out_wi ) return; - - delete[] in_lookup_x; - in_lookup_x = new int[out_wi]; - delete[] in_lookup_y; - in_lookup_y = new int[out_h]; - - switch(input->get_color_model()) { - case BC_RGBA_FLOAT: - case BC_RGBA8888: - case BC_YUVA8888: - case BC_RGBA16161616: - components = 4; - break; - } - - first = count = 0; - - for(i = out_x1i; i < out_x2i; i++) { - int in = (i - out_x1 + .5) * in_subw / out_subw + in_x1; - if(in < in_x1) - in = in_x1; - if(in > in_x2) - in = in_x2; - - if(in >= 0 && in < in_w && in >= in_x1 && i >= 0 && i < out_w) { - if(count == 0) { - first = i; - in_lookup_x[0] = in * components; - } - else { - in_lookup_x[count] = (in-last)*components; - } - last = in; - count++; - } - else if(count) - break; - } - out_x1i = first; - out_x2i = first + count; - first = count = 0; - - for(i = out_y1; i < out_y2; i++) { - int in = (i - out_y1+.5) * in_subh / out_subh + in_y1; - if(in < in_y1) in = in_y1; - if(in > in_y2) in = in_y2; - if(in >= 0 && in < in_h && i >= 0 && i < out_h) { - if(count == 0) first = i; - in_lookup_y[i] = in; - count++; - } - else if(count) - break; - } - out_y1 = first; - out_y2 = first + count; - - int rows = count; - int pkgs = get_total_packages(); - int row1 = out_y1, row2 = row1; - for(int i = 0; i < pkgs; row1=row2 ) { - NNPackage *package = (NNPackage*)get_package(i); - row2 = ++i * rows / pkgs + out_y1; - package->out_row1 = row1; - package->out_row2 = row2; - } -} - -LoadClient* NNEngine::new_client() -{ - return new NNUnit(this); -} - -LoadPackage* NNEngine::new_package() -{ - return new NNPackage; -} - -/* Fully resampled scale / translate / blend ******************************/ -/* resample into a temporary row vector, then blend */ - -#define XSAMPLE(FN, temp_type, type, max, components, ofs, round) { \ - float temp[oh*components]; \ - temp_type opcty = fade * max + round, trnsp = max - opcty; \ - type **output_rows = (type**)voutput->get_rows() + o1i; \ - type **input_rows = (type**)vinput->get_rows(); \ - \ - for(int i = pkg->out_col1; i < pkg->out_col2; i++) { \ - type *input = input_rows[i - engine->col_out1 + engine->row_in]; \ - float *tempp = temp; \ - if( !k ) { /* direct copy case */ \ - type *ip = input + i1i * components; \ - for(int j = 0; j < oh; j++) { \ - *tempp++ = *ip++; \ - *tempp++ = *ip++ - ofs; \ - *tempp++ = *ip++ - ofs; \ - if( components == 4 ) *tempp++ = *ip++; \ - } \ - } \ - else { /* resample */ \ - for(int j = 0; j < oh; j++) { \ - float racc=0.f, gacc=0.f, bacc=0.f, aacc=0.f; \ - int ki = lookup_sk[j], x = lookup_sx0[j]; \ - type *ip = input + x * components; \ - float wacc = 0, awacc = 0; \ - while(x++ < lookup_sx1[j]) { \ - float kv = k[abs(ki >> INDEX_FRACTION)]; \ - /* handle fractional pixels on edges of input */ \ - if(x == i1i) kv *= i1f; \ - if(x + 1 == i2i) kv *= i2f; \ - if( components == 4 ) { awacc += kv; kv *= ip[3]; } \ - wacc += kv; \ - racc += kv * *ip++; \ - gacc += kv * (*ip++ - ofs); \ - bacc += kv * (*ip++ - ofs); \ - if( components == 4 ) { aacc += kv; ++ip; } \ - ki += kd; \ - } \ - if(wacc > 0.) wacc = 1. / wacc; \ - *tempp++ = racc * wacc; \ - *tempp++ = gacc * wacc; \ - *tempp++ = bacc * wacc; \ - if( components == 4 ) { \ - if(awacc > 0.) awacc = 1. / awacc; \ - *tempp++ = aacc * awacc; \ - } \ - } \ - } \ - \ - /* handle fractional pixels on edges of output */ \ - temp[0] *= o1f; temp[1] *= o1f; temp[2] *= o1f; \ - if( components == 4 ) temp[3] *= o1f; \ - tempp = temp + (oh-1)*components; \ - tempp[0] *= o2f; tempp[1] *= o2f; tempp[2] *= o2f; \ - if( components == 4 ) tempp[3] *= o2f; \ - tempp = temp; \ - /* blend output */ \ - for(int j = 0; j < oh; j++) { \ - type *output = output_rows[j] + i * components; \ - if( components == 4 ) { \ - temp_type r, g, b, a; \ - ALPHA4_BLEND(FN, temp_type, tempp, output, max, 0, ofs, round); \ - ALPHA4_STORE(output, ofs, max); \ - } \ - else { \ - temp_type r, g, b; \ - ALPHA3_BLEND(FN, temp_type, tempp, output, max, 0, ofs, round); \ - ALPHA3_STORE(output, ofs, max); \ - } \ - tempp += components; \ - } \ - } \ - break; \ -} - -#define XBLEND_SAMPLE(FN) { \ - switch(vinput->get_color_model()) { \ - case BC_RGB_FLOAT: XSAMPLE(FN, z_float, z_float, 1.f, 3, 0.f, 0.f); \ - case BC_RGBA_FLOAT: XSAMPLE(FN, z_float, z_float, 1.f, 4, 0.f, 0.f); \ - case BC_RGB888: XSAMPLE(FN, z_int32_t, z_uint8_t, 0xff, 3, 0, .5f); \ - case BC_YUV888: XSAMPLE(FN, z_int32_t, z_uint8_t, 0xff, 3, 0x80, .5f); \ - case BC_RGBA8888: XSAMPLE(FN, z_int32_t, z_uint8_t, 0xff, 4, 0, .5f); \ - case BC_YUVA8888: XSAMPLE(FN, z_int32_t, z_uint8_t, 0xff, 4, 0x80, .5f); \ - case BC_RGB161616: XSAMPLE(FN, z_int64_t, z_uint16_t, 0xffff, 3, 0, .5f); \ - case BC_YUV161616: XSAMPLE(FN, z_int64_t, z_uint16_t, 0xffff, 3, 0x8000, .5f); \ - case BC_RGBA16161616: XSAMPLE(FN, z_int64_t, z_uint16_t, 0xffff, 4, 0, .5f); \ - case BC_YUVA16161616: XSAMPLE(FN, z_int64_t, z_uint16_t, 0xffff, 4, 0x8000, .5f); \ - } \ - break; \ -} - - -SamplePackage::SamplePackage() -{ -} - -SampleUnit::SampleUnit(SampleEngine *server) - : LoadClient(server) -{ - this->engine = server; -} - -SampleUnit::~SampleUnit() -{ -} - -void SampleUnit::process_package(LoadPackage *package) -{ - SamplePackage *pkg = (SamplePackage*)package; - - float i1 = engine->in1; - float i2 = engine->in2; - float o1 = engine->out1; - float o2 = engine->out2; - - if(i2 - i1 <= 0 || o2 - o1 <= 0) - return; - - VFrame *voutput = engine->output; - VFrame *vinput = engine->input; - int mode = engine->mode; - float fade = - BC_CModels::has_alpha(vinput->get_color_model()) && - mode == TRANSFER_REPLACE ? 1.f : engine->alpha; - - //int iw = vinput->get_w(); - int i1i = floor(i1); - int i2i = ceil(i2); - float i1f = 1.f - i1 + i1i; - float i2f = 1.f - i2i + i2; - - int o1i = floor(o1); - int o2i = ceil(o2); - float o1f = 1.f - o1 + o1i; - float o2f = 1.f - o2i + o2; - int oh = o2i - o1i; - - float *k = engine->kernel->lookup; - //float kw = engine->kernel->width; - //int kn = engine->kernel->n; - int kd = engine->kd; - - int *lookup_sx0 = engine->lookup_sx0; - int *lookup_sx1 = engine->lookup_sx1; - int *lookup_sk = engine->lookup_sk; - //float *lookup_wacc = engine->lookup_wacc; - - switch( mode ) { - case TRANSFER_NORMAL: XBLEND_SAMPLE(NORMAL); - case TRANSFER_ADDITION: XBLEND_SAMPLE(ADDITION); - case TRANSFER_SUBTRACT: XBLEND_SAMPLE(SUBTRACT); - case TRANSFER_MULTIPLY: XBLEND_SAMPLE(MULTIPLY); - case TRANSFER_DIVIDE: XBLEND_SAMPLE(DIVIDE); - case TRANSFER_REPLACE: XBLEND_SAMPLE(REPLACE); - case TRANSFER_MAX: XBLEND_SAMPLE(MAX); - case TRANSFER_MIN: XBLEND_SAMPLE(MIN); - case TRANSFER_AVERAGE: XBLEND_SAMPLE(AVERAGE); - case TRANSFER_DARKEN: XBLEND_SAMPLE(DARKEN); - case TRANSFER_LIGHTEN: XBLEND_SAMPLE(LIGHTEN); - case TRANSFER_DST: XBLEND_SAMPLE(DST); - case TRANSFER_DST_ATOP: XBLEND_SAMPLE(DST_ATOP); - case TRANSFER_DST_IN: XBLEND_SAMPLE(DST_IN); - case TRANSFER_DST_OUT: XBLEND_SAMPLE(DST_OUT); - case TRANSFER_DST_OVER: XBLEND_SAMPLE(DST_OVER); - case TRANSFER_SRC: XBLEND_SAMPLE(SRC); - case TRANSFER_SRC_ATOP: XBLEND_SAMPLE(SRC_ATOP); - case TRANSFER_SRC_IN: XBLEND_SAMPLE(SRC_IN); - case TRANSFER_SRC_OUT: XBLEND_SAMPLE(SRC_OUT); - case TRANSFER_SRC_OVER: XBLEND_SAMPLE(SRC_OVER); - case TRANSFER_OR: XBLEND_SAMPLE(OR); - case TRANSFER_XOR: XBLEND_SAMPLE(XOR); - } -} - - -SampleEngine::SampleEngine(int cpus) - : LoadServer(cpus, cpus) -{ - lookup_sx0 = 0; - lookup_sx1 = 0; - lookup_sk = 0; - lookup_wacc = 0; - kd = 0; -} - -SampleEngine::~SampleEngine() -{ - if(lookup_sx0) delete [] lookup_sx0; - if(lookup_sx1) delete [] lookup_sx1; - if(lookup_sk) delete [] lookup_sk; - if(lookup_wacc) delete [] lookup_wacc; -} - -/* - * unlike the Direct and NN engines, the Sample engine works across - * output columns (it makes for more economical memory addressing - * during convolution) - */ -void SampleEngine::init_packages() -{ - int iw = input->get_w(); - int i1i = floor(in1); - int i2i = ceil(in2); - float i1f = 1.f - in1 + i1i; - float i2f = 1.f - i2i + in2; - - int oy = floor(out1); - float oyf = out1 - oy; - int oh = ceil(out2) - oy; - - float *k = kernel->lookup; - float kw = kernel->width; - int kn = kernel->n; - - if(in2 - in1 <= 0 || out2 - out1 <= 0) - return; - - /* determine kernel spatial coverage */ - float scale = (out2 - out1) / (in2 - in1); - float iscale = (in2 - in1) / (out2 - out1); - float coverage = fabs(1.f / scale); - float bound = (coverage < 1.f ? kw : kw * coverage) - (.5f / TRANSFORM_SPP); - float coeff = (coverage < 1.f ? 1.f : scale) * TRANSFORM_SPP; - - delete [] lookup_sx0; - delete [] lookup_sx1; - delete [] lookup_sk; - delete [] lookup_wacc; - - lookup_sx0 = new int[oh]; - lookup_sx1 = new int[oh]; - lookup_sk = new int[oh]; - lookup_wacc = new float[oh]; - - kd = (double)coeff * (1 << INDEX_FRACTION) + .5; - - /* precompute kernel values and weight sums */ - for(int i = 0; i < oh; i++) { - /* map destination back to source */ - double sx = (i - oyf + .5) * iscale + in1 - .5; - - /* - * clip iteration to source area but not source plane. Points - * outside the source plane count as transparent. Points outside - * the source area don't count at all. The actual convolution - * later will be clipped to both, but we need to compute - * weights. - */ - int sx0 = MAX((int)floor(sx - bound) + 1, i1i); - int sx1 = MIN((int)ceil(sx + bound), i2i); - int ki = (double)(sx0 - sx) * coeff * (1 << INDEX_FRACTION) - + (1 << (INDEX_FRACTION - 1)) + .5; - float wacc=0.; - - lookup_sx0[i] = -1; - lookup_sx1[i] = -1; - - for(int j= sx0; j < sx1; j++) { - int kv = (ki >> INDEX_FRACTION); - if(kv > kn) break; - if(kv >= -kn) { - /* - * the contribution of the first and last input pixel (if - * fractional) are linearly weighted by the fraction - */ - if(j == i1i) - wacc += k[abs(kv)] * i1f; - else if(j + 1 == i2i) - wacc += k[abs(kv)] * i2f; - else - wacc += k[abs(kv)]; - - /* this is where we clip the kernel convolution to the source plane */ - if(j >= 0 && j < iw) { - if(lookup_sx0[i] == -1) { - lookup_sx0[i] = j; - lookup_sk[i] = ki; - } - lookup_sx1[i] = j + 1; - } - } - ki += kd; - } - lookup_wacc[i] = wacc > 0. ? 1. / wacc : 0.; - } - - int cols = col_out2 - col_out1; - int pkgs = get_total_packages(); - int col1 = col_out1, col2 = col1; - for(int i = 0; i < pkgs; col1=col2 ) { - SamplePackage *package = (SamplePackage*)get_package(i); - col2 = ++i * cols / pkgs + col_out1; - package->out_col1 = col1; - package->out_col2 = col2; - } -} - -LoadClient* SampleEngine::new_client() -{ - return new SampleUnit(this); -} - -LoadPackage* SampleEngine::new_package() -{ - return new SamplePackage; -} diff --git a/cinelerra-5.1/cinelerra/overlayframe.C.clamp b/cinelerra-5.1/cinelerra/overlayframe.C.clamp deleted file mode 100644 index c3ce4f1c..00000000 --- a/cinelerra-5.1/cinelerra/overlayframe.C.clamp +++ /dev/null @@ -1,1796 +0,0 @@ -#include -#include -#include -#include - -#include "clip.h" -#include "edl.inc" -#include "mutex.h" -#include "overlayframe.h" -#include "vframe.h" - -OverlayFrame::OverlayFrame(int cpus) -{ - temp_frame = 0; - blend_engine = 0; - scale_engine = 0; - scaletranslate_engine = 0; - translate_engine = 0; - this->cpus = cpus; -} - -OverlayFrame::~OverlayFrame() -{ -//printf("OverlayFrame::~OverlayFrame 1\n"); - if(temp_frame) delete temp_frame; - if(scale_engine) delete scale_engine; - if(translate_engine) delete translate_engine; - if(blend_engine) delete blend_engine; - if(scaletranslate_engine) delete scaletranslate_engine; -//printf("OverlayFrame::~OverlayFrame 2\n"); -} - - - - - - - - -// Verification: - -// (255 * 255 + 0 * 0) / 255 = 255 -// (255 * 127 + 255 * (255 - 127)) / 255 = 255 - -// (65535 * 65535 + 0 * 0) / 65535 = 65535 -// (65535 * 32767 + 65535 * (65535 - 32767)) / 65535 = 65535 - - -// Branch prediction 4 U - -#define BLEND_3(max, type) \ -{ \ - int64_t r, g, b; \ - \ -/* if(mode != TRANSFER_NORMAL) printf("BLEND mode = %d\n", mode); */ \ - switch(mode) \ - { \ - case TRANSFER_DIVIDE: \ - r = output[0] ? (((int64_t)input1 * max) / output[0]) : max; \ - g = output[1] ? (((int64_t)input2 * max) / output[1]) : max; \ - b = output[2] ? (((int64_t)input3 * max) / output[2]) : max; \ - r = (r * opacity + output[0] * transparency) / max; \ - g = (g * opacity + output[1] * transparency) / max; \ - b = (b * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_MULTIPLY: \ - r = ((int64_t)input1 * output[0]) / max; \ - g = ((int64_t)input2 * output[1]) / max; \ - b = ((int64_t)input3 * output[2]) / max; \ - r = (r * opacity + output[0] * transparency) / max; \ - g = (g * opacity + output[1] * transparency) / max; \ - b = (b * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_SUBTRACT: \ - r = (((int64_t)input1 - output[0]) * opacity + output[0] * transparency) / max; \ - g = (((int64_t)input2 - output[1]) * opacity + output[1] * transparency) / max; \ - b = (((int64_t)input3 - output[2]) * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_ADDITION: \ - r = (((int64_t)input1 + output[0]) * opacity + output[0] * transparency) / max; \ - g = (((int64_t)input2 + output[1]) * opacity + output[1] * transparency) / max; \ - b = (((int64_t)input3 + output[2]) * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_REPLACE: \ - r = input1; \ - g = input2; \ - b = input3; \ - break; \ - case TRANSFER_NORMAL: \ - r = ((int64_t)input1 * opacity + output[0] * transparency) / max; \ - g = ((int64_t)input2 * opacity + output[1] * transparency) / max; \ - b = ((int64_t)input3 * opacity + output[2] * transparency) / max; \ - break; \ - } \ - \ - output[0] = (type)CLIP(r, 0, max); \ - output[1] = (type)CLIP(g, 0, max); \ - output[2] = (type)CLIP(b, 0, max); \ -} - - - - - -// Blending equations are drastically different for 3 and 4 components -#define BLEND_4(max, type) \ -{ \ - int64_t r, g, b, a; \ - int64_t pixel_opacity, pixel_transparency; \ - \ - pixel_opacity = opacity * input4 / max; \ - pixel_transparency = (max - pixel_opacity) * output[3] / max; \ - \ - switch(mode) \ - { \ - case TRANSFER_DIVIDE: \ - r = output[0] ? (((int64_t)input1 * max) / output[0]) : max; \ - g = output[1] ? (((int64_t)input2 * max) / output[1]) : max; \ - b = output[2] ? (((int64_t)input3 * max) / output[2]) : max; \ - r = (r * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (g * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (b * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_MULTIPLY: \ - r = ((int64_t)input1 * output[0]) / max; \ - g = ((int64_t)input2 * output[1]) / max; \ - b = ((int64_t)input3 * output[2]) / max; \ - r = (r * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (g * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (b * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_SUBTRACT: \ - r = (((int64_t)input1 - output[0]) * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (((int64_t)input2 - output[1]) * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (((int64_t)input3 - output[2]) * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_ADDITION: \ - r = (((int64_t)input1 + output[0]) * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (((int64_t)input2 + output[1]) * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (((int64_t)input3 + output[2]) * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_REPLACE: \ - r = input1; \ - g = input2; \ - b = input3; \ - a = input4; \ - break; \ - case TRANSFER_NORMAL: \ - r = ((int64_t)input1 * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = ((int64_t)input2 * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = ((int64_t)input3 * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - } \ - \ - output[0] = (type)CLIP(r, 0, max); \ - output[1] = (type)CLIP(g, 0, max); \ - output[2] = (type)CLIP(b, 0, max); \ - output[3] = (type)a; \ -} - - - - - - - - -// Bicubic algorithm using multiprocessors -// input -> scale nearest integer boundaries -> temp -> translation -> blend -> output - -// Nearest neighbor algorithm using multiprocessors for blending -// input -> scale + translate -> blend -> output - - -int OverlayFrame::overlay(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, // 0 - 1 - int mode, - int interpolation_type) -{ - float w_scale = (out_x2 - out_x1) / (in_x2 - in_x1); - float h_scale = (out_y2 - out_y1) / (in_y2 - in_y1); - -//printf("OverlayFrame::overlay 1 %d %f\n", mode, alpha); -// Limit values - if(in_x1 < 0) - { - out_x1 += -in_x1 * w_scale; - in_x1 = 0; - } - else - if(in_x1 >= input->get_w()) - { - out_x1 -= (in_x1 - input->get_w()) * w_scale; - in_x1 = input->get_w(); - } - - if(in_y1 < 0) - { - out_y1 += -in_y1 * h_scale; - in_y1 = 0; - } - else - if(in_y1 >= input->get_h()) - { - out_y1 -= (in_y1 - input->get_h()) * h_scale; - in_y1 = input->get_h(); - } - - if(in_x2 < 0) - { - out_x2 += -in_x2 * w_scale; - in_x2 = 0; - } - else - if(in_x2 >= input->get_w()) - { - out_x2 -= (in_x2 - input->get_w()) * w_scale; - in_x2 = input->get_w(); - } - - if(in_y2 < 0) - { - out_y2 += -in_y2 * h_scale; - in_y2 = 0; - } - else - if(in_y2 >= input->get_h()) - { - out_y2 -= (in_y2 - input->get_h()) * h_scale; - in_y2 = input->get_h(); - } - - if(out_x1 < 0) - { - in_x1 += -out_x1 / w_scale; - out_x1 = 0; - } - else - if(out_x1 >= output->get_w()) - { - in_x1 -= (out_x1 - output->get_w()) / w_scale; - out_x1 = output->get_w(); - } - - if(out_y1 < 0) - { - in_y1 += -out_y1 / h_scale; - out_y1 = 0; - } - else - if(out_y1 >= output->get_h()) - { - in_y1 -= (out_y1 - output->get_h()) / h_scale; - out_y1 = output->get_h(); - } - - if(out_x2 < 0) - { - in_x2 += -out_x2 / w_scale; - out_x2 = 0; - } - else - if(out_x2 >= output->get_w()) - { - in_x2 -= (out_x2 - output->get_w()) / w_scale; - out_x2 = output->get_w(); - } - - if(out_y2 < 0) - { - in_y2 += -out_y2 / h_scale; - out_y2 = 0; - } - else - if(out_y2 >= output->get_h()) - { - in_y2 -= (out_y2 - output->get_h()) / h_scale; - out_y2 = output->get_h(); - } - - - - - - float in_w = in_x2 - in_x1; - float in_h = in_y2 - in_y1; - float out_w = out_x2 - out_x1; - float out_h = out_y2 - out_y1; -// Input for translation operation - VFrame *translation_input = input; - - - -// printf("OverlayFrame::overlay %f %f %f %f -> %f %f %f %f\n", in_x1, -// in_y1, -// in_x2, -// in_y2, -// out_x1, -// out_y1, -// out_x2, -// out_y2); - - - - - -// **************************************************************************** -// Transfer to temp buffer by scaling nearest integer boundaries -// **************************************************************************** - if(interpolation_type != NEAREST_NEIGHBOR && - (!EQUIV(w_scale, 1) || !EQUIV(h_scale, 1))) - { -// Create integer boundaries for interpolation - int in_x1_int = (int)in_x1; - int in_y1_int = (int)in_y1; - int in_x2_int = MIN((int)ceil(in_x2), input->get_w()); - int in_y2_int = MIN((int)ceil(in_y2), input->get_h()); - -// Dimensions of temp frame. Integer boundaries scaled. - int temp_w = (int)ceil(w_scale * (in_x2_int - in_x1_int)); - int temp_h = (int)ceil(h_scale * (in_y2_int - in_y1_int)); - VFrame *scale_output; - - - -#define NO_TRANSLATION1 \ - (EQUIV(in_x1, 0) && \ - EQUIV(in_y1, 0) && \ - EQUIV(out_x1, 0) && \ - EQUIV(out_y1, 0) && \ - EQUIV(in_x2, in_x2_int) && \ - EQUIV(in_y2, in_y2_int) && \ - EQUIV(out_x2, temp_w) && \ - EQUIV(out_y2, temp_h)) - - -#define NO_BLEND \ - (EQUIV(alpha, 1) && \ - (mode == TRANSFER_REPLACE || \ - (mode == TRANSFER_NORMAL && cmodel_components(input->get_color_model()) == 3))) - - - - - -// Prepare destination for operation - -// No translation and no blending. The blending operation is built into the -// translation unit but not the scaling unit. -// input -> output - if(NO_TRANSLATION1 && - NO_BLEND) - { -// printf("OverlayFrame::overlay input -> output\n"); - - scale_output = output; - translation_input = 0; - } - else -// If translation or blending -// input -> nearest integer boundary temp - { - if(temp_frame && - (temp_frame->get_w() != temp_w || - temp_frame->get_h() != temp_h)) - { - delete temp_frame; - temp_frame = 0; - } - - if(!temp_frame) - { - temp_frame = new VFrame(0, - temp_w, - temp_h, - input->get_color_model(), - -1); - } -//printf("OverlayFrame::overlay input -> temp\n"); - - - temp_frame->clear_frame(); - -// printf("OverlayFrame::overlay 4 temp_w=%d temp_h=%d\n", -// temp_w, temp_h); - scale_output = temp_frame; - translation_input = scale_output; - -// Adjust input coordinates to reflect new scaled coordinates. - in_x1 = (in_x1 - in_x1_int) * w_scale; - in_y1 = (in_y1 - in_y1_int) * h_scale; - in_x2 = (in_x2 - in_x1_int) * w_scale; - in_y2 = (in_y2 - in_y1_int) * h_scale; - } - - - -//printf("Overlay 1\n"); - -// Scale input -> scale_output - if(!scale_engine) scale_engine = new ScaleEngine(this, cpus); - scale_engine->scale_output = scale_output; - scale_engine->scale_input = input; - scale_engine->w_scale = w_scale; - scale_engine->h_scale = h_scale; - scale_engine->in_x1_int = in_x1_int; - scale_engine->in_y1_int = in_y1_int; - scale_engine->out_w_int = temp_w; - scale_engine->out_h_int = temp_h; - scale_engine->interpolation_type = interpolation_type; -//printf("Overlay 2\n"); - -//printf("OverlayFrame::overlay ScaleEngine 1 %d\n", out_h_int); - scale_engine->process_packages(); -//printf("OverlayFrame::overlay ScaleEngine 2\n"); - - - - } - -// printf("OverlayFrame::overlay 1 %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", -// in_x1, -// in_y1, -// in_x2, -// in_y2, -// out_x1, -// out_y1, -// out_x2, -// out_y2); - - - - - -#define NO_TRANSLATION2 \ - (EQUIV(in_x1, 0) && \ - EQUIV(in_y1, 0) && \ - EQUIV(in_x2, translation_input->get_w()) && \ - EQUIV(in_y2, translation_input->get_h()) && \ - EQUIV(out_x1, 0) && \ - EQUIV(out_y1, 0) && \ - EQUIV(out_x2, output->get_w()) && \ - EQUIV(out_y2, output->get_h())) \ - -#define NO_SCALE \ - (EQUIV(out_x2 - out_x1, in_x2 - in_x1) && \ - EQUIV(out_y2 - out_y1, in_y2 - in_y1)) - - - - -//printf("OverlayFrame::overlay 4 %d\n", mode); - - - - - if(translation_input) - { -// Direct copy - if( NO_TRANSLATION2 && - NO_SCALE && - NO_BLEND) - { -//printf("OverlayFrame::overlay direct copy\n"); - output->copy_from(translation_input); - } - else -// Blend only - if( NO_TRANSLATION2 && - NO_SCALE) - { - if(!blend_engine) blend_engine = new BlendEngine(this, cpus); - - - blend_engine->output = output; - blend_engine->input = translation_input; - blend_engine->alpha = alpha; - blend_engine->mode = mode; - - blend_engine->process_packages(); - } - else -// Scale and translate using nearest neighbor -// Translation is exactly on integer boundaries - if(interpolation_type == NEAREST_NEIGHBOR || - EQUIV(in_x1, (int)in_x1) && - EQUIV(in_y1, (int)in_y1) && - EQUIV(in_x2, (int)in_x2) && - EQUIV(in_y2, (int)in_y2) && - - EQUIV(out_x1, (int)out_x1) && - EQUIV(out_y1, (int)out_y1) && - EQUIV(out_x2, (int)out_x2) && - EQUIV(out_y2, (int)out_y2)) - { -//printf("OverlayFrame::overlay NEAREST_NEIGHBOR 1\n"); - if(!scaletranslate_engine) scaletranslate_engine = new ScaleTranslateEngine(this, cpus); - - - scaletranslate_engine->output = output; - scaletranslate_engine->input = translation_input; - scaletranslate_engine->in_x1 = (int)in_x1; - scaletranslate_engine->in_y1 = (int)in_y1; - scaletranslate_engine->in_x2 = (int)in_x2; - scaletranslate_engine->in_y2 = (int)in_y2; - scaletranslate_engine->out_x1 = (int)out_x1; - scaletranslate_engine->out_y1 = (int)out_y1; - scaletranslate_engine->out_x2 = (int)out_x2; - scaletranslate_engine->out_y2 = (int)out_y2; - scaletranslate_engine->alpha = alpha; - scaletranslate_engine->mode = mode; - - scaletranslate_engine->process_packages(); - } - else -// Fractional translation - { -// Use fractional translation -// printf("OverlayFrame::overlay temp -> output %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", -// in_x1, -// in_y1, -// in_x2, -// in_y2, -// out_x1, -// out_y1, -// out_x2, -// out_y2); - -//printf("Overlay 3\n"); - if(!translate_engine) translate_engine = new TranslateEngine(this, cpus); - translate_engine->translate_output = output; - translate_engine->translate_input = translation_input; - translate_engine->translate_in_x1 = in_x1; - translate_engine->translate_in_y1 = in_y1; - translate_engine->translate_in_x2 = in_x2; - translate_engine->translate_in_y2 = in_y2; - translate_engine->translate_out_x1 = out_x1; - translate_engine->translate_out_y1 = out_y1; - translate_engine->translate_out_x2 = out_x2; - translate_engine->translate_out_y2 = out_y2; - translate_engine->translate_alpha = alpha; - translate_engine->translate_mode = mode; -//printf("Overlay 4\n"); - -//printf("OverlayFrame::overlay 5 %d\n", mode); - translate_engine->process_packages(); - - } - } -//printf("OverlayFrame::overlay 2\n"); - - return 0; -} - - - - - - - -ScalePackage::ScalePackage() -{ -} - - - - -ScaleUnit::ScaleUnit(ScaleEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; - this->engine = server; -} - -ScaleUnit::~ScaleUnit() -{ -} - - - -#define BILINEAR(max, type, components) \ -{ \ - float k_y = 1.0 / scale_h; \ - float k_x = 1.0 / scale_w; \ - type **in_rows = (type**)input->get_rows(); \ - type **out_rows = (type**)output->get_rows(); \ - int out_h = pkg->out_row2 - pkg->out_row1; \ - int in_h_int = input->get_h(); \ - int in_w_int = input->get_w(); \ - int *table_int_x1, *table_int_y1; \ - int *table_int_x2, *table_int_y2; \ - float *table_frac_x, *table_antifrac_x, *table_frac_y, *table_antifrac_y; \ - \ - tabulate_blinear(table_int_x1, \ - table_int_x2, \ - table_frac_x, \ - table_antifrac_x, \ - k_x, \ - 0, \ - out_w_int, \ - in_x1_int, \ - in_w_int); \ - tabulate_blinear(table_int_y1, \ - table_int_y2, \ - table_frac_y, \ - table_antifrac_y, \ - k_y, \ - pkg->out_row1, \ - pkg->out_row2, \ - in_y1_int, \ - in_h_int); \ - \ - for(int i = 0; i < out_h; i++) \ - { \ - int i_y1 = table_int_y1[i]; \ - int i_y2 = table_int_y2[i]; \ - float a = table_frac_y[i]; \ - float anti_a = table_antifrac_y[i]; \ - type *in_row1 = in_rows[i_y1]; \ - type *in_row2 = in_rows[i_y2]; \ - type *out_row = out_rows[i + pkg->out_row1]; \ - \ - for(int j = 0; j < out_w_int; j++) \ - { \ - int i_x1 = table_int_x1[j]; \ - int i_x2 = table_int_x2[j]; \ - float b = table_frac_x[j]; \ - float anti_b = table_antifrac_x[j]; \ - float output1r, output1g, output1b, output1a; \ - float output2r, output2g, output2b, output2a; \ - float output3r, output3g, output3b, output3a; \ - float output4r, output4g, output4b, output4a; \ - \ - output1r = in_row1[i_x1 * components]; \ - output1g = in_row1[i_x1 * components + 1]; \ - output1b = in_row1[i_x1 * components + 2]; \ - if(components == 4) output1a = in_row1[i_x1 * components + 3]; \ - \ - output2r = in_row1[i_x2 * components]; \ - output2g = in_row1[i_x2 * components + 1]; \ - output2b = in_row1[i_x2 * components + 2]; \ - if(components == 4) output2a = in_row1[i_x2 * components + 3]; \ - \ - output3r = in_row2[i_x1 * components]; \ - output3g = in_row2[i_x1 * components + 1]; \ - output3b = in_row2[i_x1 * components + 2]; \ - if(components == 4) output3a = in_row2[i_x1 * components + 3]; \ -\ - output4r = in_row2[i_x2 * components]; \ - output4g = in_row2[i_x2 * components + 1]; \ - output4b = in_row2[i_x2 * components + 2]; \ - if(components == 4) output4a = in_row2[i_x2 * components + 3]; \ - \ - out_row[j * components] = \ - (type)((anti_a) * (((anti_b) * output1r) + \ - (b * output2r)) + \ - a * (((anti_b) * output3r) + \ - (b * output4r))); \ - out_row[j * components + 1] = \ - (type)((anti_a) * (((anti_b) * output1g) + \ - (b * output2g)) + \ - a * (((anti_b) * output3g) + \ - (b * output4g))); \ - out_row[j * components + 2] = \ - (type)((anti_a) * (((anti_b) * output1b) + \ - (b * output2b)) + \ - a * (((anti_b) * output3b) + \ - (b * output4b))); \ - if(components == 4) \ - out_row[j * components + 3] = \ - (type)((anti_a) * (((anti_b) * output1a) + \ - (b * output2a)) + \ - a * (((anti_b) * output3a) + \ - (b * output4a))); \ - } \ - } \ - \ - \ - delete [] table_int_x1; \ - delete [] table_int_x2; \ - delete [] table_frac_x; \ - delete [] table_antifrac_x; \ - delete [] table_int_y1; \ - delete [] table_int_y2; \ - delete [] table_frac_y; \ - delete [] table_antifrac_y; \ - \ -} - - -#define BICUBIC(max, type, components) \ -{ \ - float k_y = 1.0 / scale_h; \ - float k_x = 1.0 / scale_w; \ - type **in_rows = (type**)input->get_rows(); \ - type **out_rows = (type**)output->get_rows(); \ - float *bspline_x, *bspline_y; \ - int *in_x_table, *in_y_table; \ - int in_h_int = input->get_h(); \ - int in_w_int = input->get_w(); \ - \ - tabulate_bicubic(bspline_x, \ - in_x_table, \ - k_x, \ - in_x1_int, \ - out_w_int, \ - in_w_int, \ - -1); \ - \ - tabulate_bicubic(bspline_y, \ - in_y_table, \ - k_y, \ - in_y1_int, \ - out_h_int, \ - in_h_int, \ - 1); \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) \ - { \ - for(int j = 0; j < out_w_int; j++) \ - { \ - int i_x = (int)(k_x * j); \ - float output1, output2, output3, output4; \ - output1 = 0; \ - output2 = 0; \ - output3 = 0; \ - if(components == 4) \ - output4 = 0; \ - int table_y = i * 4; \ - \ -/* Kernel */ \ - for(int m = -1; m < 3; m++) \ - { \ - float r1 = bspline_y[table_y]; \ - int y = in_y_table[table_y]; \ - int table_x = j * 4; \ - \ - for(int n = -1; n < 3; n++) \ - { \ - float r2 = bspline_x[table_x]; \ - int x = in_x_table[table_x]; \ - float r_square = r1 * r2; \ - \ - output1 += r_square * in_rows[y][x * components]; \ - output2 += r_square * in_rows[y][x * components + 1]; \ - output3 += r_square * in_rows[y][x * components + 2]; \ - if(components == 4) \ - output4 += r_square * in_rows[y][x * components + 3]; \ - \ - table_x++; \ - } \ - table_y++; \ - } \ - \ - \ - out_rows[i][j * components] = (type)output1; \ - out_rows[i][j * components + 1] = (type)output2; \ - out_rows[i][j * components + 2] = (type)output3; \ - if(components == 4) \ - out_rows[i][j * components + 3] = (type)output4; \ - \ - } \ - } \ - \ - delete [] bspline_x; \ - delete [] bspline_y; \ - delete [] in_x_table; \ - delete [] in_y_table; \ -} - - - - -// Pow function is not thread safe in Compaqt C -#define CUBE(x) ((x) * (x) * (x)) - -float ScaleUnit::cubic_bspline(float x) -{ - float a, b, c, d; - - if((x + 2.0F) <= 0.0F) - { - a = 0.0F; - } - else - { - a = CUBE(x + 2.0F); - } - - - if((x + 1.0F) <= 0.0F) - { - b = 0.0F; - } - else - { - b = CUBE(x + 1.0F); - } - - if(x <= 0) - { - c = 0.0F; - } - else - { - c = CUBE(x); - } - - if((x - 1.0F) <= 0.0F) - { - d = 0.0F; - } - else - { - d = CUBE(x - 1.0F); - } - - - return (a - (4.0F * b) + (6.0F * c) - (4.0F * d)) / 6.0; -} - - -void ScaleUnit::tabulate_bicubic(float* &coef_table, - int* &coord_table, - float scale, - int start, - int pixels, - int total_pixels, - float coefficient) -{ - coef_table = new float[pixels * 4]; - coord_table = new int[pixels * 4]; - for(int i = 0, j = 0; i < pixels; i++) - { - float f_x = (float)i * scale; - float a = f_x - floor(f_x); - - for(float m = -1; m < 3; m++) - { - coef_table[j] = cubic_bspline(coefficient * (m - a)); - coord_table[j] = start + (int)f_x + m; - CLAMP(coord_table[j], 0, total_pixels - 1); - j++; - } - - } -} - -void ScaleUnit::tabulate_blinear(int* &table_int1, - int* &table_int2, - float* &table_frac, - float* &table_antifrac, - float scale, - int pixel1, - int pixel2, - int start, - int total_pixels) -{ - table_int1 = new int[pixel2 - pixel1]; - table_int2 = new int[pixel2 - pixel1]; - table_frac = new float[pixel2 - pixel1]; - table_antifrac = new float[pixel2 - pixel1]; - - for(int i = pixel1, j = 0; i < pixel2; i++, j++) - { - float f_x = (float)i * scale; - int i_x = (int)floor(f_x); - float a = (f_x - floor(f_x)); - - table_int1[j] = i_x + start; - table_int2[j] = i_x + start + 1; - CLAMP(table_int1[j], 0, total_pixels - 1); - CLAMP(table_int2[j], 0, total_pixels - 1); - table_frac[j] = a; - table_antifrac[j] = 1.0F - a; -//printf("ScaleUnit::tabulate_blinear %d %d %d\n", j, table_int1[j], table_int2[j]); - } -} - -void ScaleUnit::process_package(LoadPackage *package) -{ - ScalePackage *pkg = (ScalePackage*)package; - -//printf("ScaleUnit::process_package 1\n"); -// Arguments for macros - VFrame *output = engine->scale_output; - VFrame *input = engine->scale_input; - float scale_w = engine->w_scale; - float scale_h = engine->h_scale; - int in_x1_int = engine->in_x1_int; - int in_y1_int = engine->in_y1_int; - int out_h_int = engine->out_h_int; - int out_w_int = engine->out_w_int; - int do_yuv = - (input->get_color_model() == BC_YUV888 || - input->get_color_model() == BC_YUVA8888 || - input->get_color_model() == BC_YUV161616 || - input->get_color_model() == BC_YUVA16161616); - -//printf("ScaleUnit::process_package 2\n"); - if(engine->interpolation_type == CUBIC_CUBIC || - (engine->interpolation_type == CUBIC_LINEAR - && engine->w_scale > 1 && - engine->h_scale > 1)) - { - - switch(engine->scale_input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - BICUBIC(0xff, unsigned char, 3); - break; - - case BC_RGBA8888: - case BC_YUVA8888: - BICUBIC(0xff, unsigned char, 4); - break; - - case BC_RGB161616: - case BC_YUV161616: - BICUBIC(0xffff, uint16_t, 3); - break; - - case BC_RGBA16161616: - case BC_YUVA16161616: - BICUBIC(0xffff, uint16_t, 4); - break; - } - } - else -// Perform bilinear scaling input -> scale_output - { - switch(engine->scale_input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - BILINEAR(0xff, unsigned char, 3); - break; - - case BC_RGBA8888: - case BC_YUVA8888: - BILINEAR(0xff, unsigned char, 4); - break; - - case BC_RGB161616: - case BC_YUV161616: - BILINEAR(0xffff, uint16_t, 3); - break; - - case BC_RGBA16161616: - case BC_YUVA16161616: - BILINEAR(0xffff, uint16_t, 4); - break; - } - } -//printf("ScaleUnit::process_package 3\n"); - -} - - - - - - - - - - - - - -ScaleEngine::ScaleEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -ScaleEngine::~ScaleEngine() -{ -} - -void ScaleEngine::init_packages() -{ - for(int i = 0; i < total_packages; i++) - { - ScalePackage *package = (ScalePackage*)packages[i]; - package->out_row1 = out_h_int / total_packages * i; - package->out_row2 = package->out_row1 + out_h_int / total_packages; - - if(i >= total_packages - 1) - package->out_row2 = out_h_int; - } -} - -LoadClient* ScaleEngine::new_client() -{ - return new ScaleUnit(this, overlay); -} - -LoadPackage* ScaleEngine::new_package() -{ - return new ScalePackage; -} - - - - - - - - - - - - - -TranslatePackage::TranslatePackage() -{ -} - - - -TranslateUnit::TranslateUnit(TranslateEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; - this->engine = server; -} - -TranslateUnit::~TranslateUnit() -{ -} - - - -void TranslateUnit::translation_array(transfer_table* &table, - float out_x1, - float out_x2, - float in_x1, - float in_x2, - int in_total, - int out_total, - int &out_x1_int, - int &out_x2_int) -{ - int out_w_int; - float offset = out_x1 - in_x1; - - out_x1_int = (int)out_x1; - out_x2_int = MIN((int)ceil(out_x2), out_total); - out_w_int = out_x2_int - out_x1_int; - - table = new transfer_table[out_w_int]; - bzero(table, sizeof(transfer_table) * out_w_int); - - -//printf("OverlayFrame::translation_array 1 %f %f -> %f %f\n", in_x1, in_x2, out_x1, out_x2); - - float in_x = in_x1; - for(int out_x = out_x1_int; out_x < out_x2_int; out_x++) - { - transfer_table *entry = &table[out_x - out_x1_int]; - - entry->in_x1 = (int)in_x; - entry->in_x2 = (int)in_x + 1; - -// Get fraction of output pixel to fill - entry->output_fraction = 1; - - if(out_x1 > out_x) - { - entry->output_fraction -= out_x1 - out_x; - } - - if(out_x2 < out_x + 1) - { - entry->output_fraction = (out_x2 - out_x); - } - -// Advance in_x until out_x_fraction is filled - float out_x_fraction = entry->output_fraction; - float in_x_fraction = floor(in_x + 1) - in_x; - - if(out_x_fraction <= in_x_fraction) - { - entry->in_fraction1 = out_x_fraction; - entry->in_fraction2 = 0.0; - in_x += out_x_fraction; - } - else - { - entry->in_fraction1 = in_x_fraction; - in_x += out_x_fraction; - entry->in_fraction2 = in_x - floor(in_x); - } - -// Clip in_x and zero out fraction. This doesn't work for YUV. - if(entry->in_x2 >= in_total) - { - entry->in_x2 = in_total - 1; - entry->in_fraction2 = 0.0; - } - - if(entry->in_x1 >= in_total) - { - entry->in_x1 = in_total - 1; - entry->in_fraction1 = 0.0; - } -// printf("OverlayFrame::translation_array 2 %d %d %d %f %f %f\n", -// out_x, -// entry->in_x1, -// entry->in_x2, -// entry->in_fraction1, -// entry->in_fraction2, -// entry->output_fraction); - } -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define TRANSLATE(max, type, components, do_yuv) \ -{ \ - \ - type **in_rows = (type**)input->get_rows(); \ - type **out_rows = (type**)output->get_rows(); \ - \ -/* printf("OverlayFrame::translate 1 %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", */ \ -/* (in_x1), in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2); */ \ - \ - unsigned int master_opacity = (int)(alpha * max + 0.5); \ - unsigned int master_transparency = max - master_opacity; \ - float zero_r, zero_g, zero_b; \ - zero_r = 0; \ - zero_b = ((max + 1) >> 1) * (do_yuv); \ - zero_g = ((max + 1) >> 1) * (do_yuv); \ - \ -/* printf("TRANSLATE %d\n", mode); */ \ - \ - for(int i = row1; i < row2; i++) \ - { \ - int in_y1 = y_table[i - out_y1_int].in_x1; \ - int in_y2 = y_table[i - out_y1_int].in_x2; \ - float y_fraction1 = y_table[i - out_y1_int].in_fraction1; \ - float y_fraction2 = y_table[i - out_y1_int].in_fraction2; \ - float y_output_fraction = y_table[i - out_y1_int].output_fraction; \ - type *in_row1 = in_rows[(in_y1)]; \ - type *in_row2 = in_rows[(in_y2)]; \ - type *out_row = out_rows[i]; \ - \ - for(int j = out_x1_int; j < out_x2_int; j++) \ - { \ - int in_x1 = x_table[j - out_x1_int].in_x1; \ - int in_x2 = x_table[j - out_x1_int].in_x2; \ - float x_fraction1 = x_table[j - out_x1_int].in_fraction1; \ - float x_fraction2 = x_table[j - out_x1_int].in_fraction2; \ - float x_output_fraction = x_table[j - out_x1_int].output_fraction; \ - type *output = &out_row[j * components]; \ - int input1, input2, input3, input4; \ - float fraction1 = x_fraction1 * y_fraction1; \ - float fraction2 = x_fraction2 * y_fraction1; \ - float fraction3 = x_fraction1 * y_fraction2; \ - float fraction4 = x_fraction2 * y_fraction2; \ - \ - input1 = (int)(in_row1[in_x1 * components] * fraction1 + \ - in_row1[in_x2 * components] * fraction2 + \ - in_row2[in_x1 * components] * fraction3 + \ - in_row2[in_x2 * components] * fraction4 + 0.5); \ - \ -/* Add chroma to fractional pixels */ \ - if(do_yuv) \ - { \ - float extra_chroma = (1.0F - \ - fraction1 - \ - fraction2 - \ - fraction3 - \ - fraction4) * zero_b; \ - input2 = (int)(in_row1[in_x1 * components + 1] * fraction1 + \ - in_row1[in_x2 * components + 1] * fraction2 + \ - in_row2[in_x1 * components + 1] * fraction3 + \ - in_row2[in_x2 * components + 1] * fraction4 + \ - extra_chroma + 0.5); \ - input3 = (int)(in_row1[in_x1 * components + 2] * fraction1 + \ - in_row1[in_x2 * components + 2] * fraction2 + \ - in_row2[in_x1 * components + 2] * fraction3 + \ - in_row2[in_x2 * components + 2] * fraction4 + \ - extra_chroma + 0.5); \ - } \ - else \ - { \ - input2 = (int)(in_row1[in_x1 * components + 1] * fraction1 + \ - in_row1[in_x2 * components + 1] * fraction2 + \ - in_row2[in_x1 * components + 1] * fraction3 + \ - in_row2[in_x2 * components + 1] * fraction4 + 0.5); \ - input3 = (int)(in_row1[in_x1 * components + 2] * fraction1 + \ - in_row1[in_x2 * components + 2] * fraction2 + \ - in_row2[in_x1 * components + 2] * fraction3 + \ - in_row2[in_x2 * components + 2] * fraction4 + 0.5); \ - } \ - \ - if(components == 4) \ - input4 = (int)(in_row1[in_x1 * components + 3] * fraction1 + \ - in_row1[in_x2 * components + 3] * fraction2 + \ - in_row2[in_x1 * components + 3] * fraction3 + \ - in_row2[in_x2 * components + 3] * fraction4 + 0.5); \ - \ - unsigned int opacity = (int)(master_opacity * \ - y_output_fraction * \ - x_output_fraction + 0.5); \ - unsigned int transparency = max - opacity; \ - \ -/* if(opacity != max) printf("TRANSLATE %x %d %d\n", opacity, j, i); */ \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - } \ - } \ -} - -void TranslateUnit::process_package(LoadPackage *package) -{ - TranslatePackage *pkg = (TranslatePackage*)package; - int out_y1_int; - int out_y2_int; - int out_x1_int; - int out_x2_int; - - -// Variables for TRANSLATE - VFrame *input = engine->translate_input; - VFrame *output = engine->translate_output; - float in_x1 = engine->translate_in_x1; - float in_y1 = engine->translate_in_y1; - float in_x2 = engine->translate_in_x2; - float in_y2 = engine->translate_in_y2; - float out_x1 = engine->translate_out_x1; - float out_y1 = engine->translate_out_y1; - float out_x2 = engine->translate_out_x2; - float out_y2 = engine->translate_out_y2; - float alpha = engine->translate_alpha; - int row1 = pkg->out_row1; - int row2 = pkg->out_row2; - int mode = engine->translate_mode; - int in_total_x = input->get_w(); - int in_total_y = input->get_h(); - int do_yuv = - (engine->translate_input->get_color_model() == BC_YUV888 || - engine->translate_input->get_color_model() == BC_YUVA8888 || - engine->translate_input->get_color_model() == BC_YUV161616 || - engine->translate_input->get_color_model() == BC_YUVA16161616); - - transfer_table *x_table; - transfer_table *y_table; - - translation_array(x_table, - out_x1, - out_x2, - in_x1, - in_x2, - in_total_x, - output->get_w(), - out_x1_int, - out_x2_int); - translation_array(y_table, - out_y1, - out_y2, - in_y1, - in_y2, - in_total_y, - output->get_h(), - out_y1_int, - out_y2_int); - - switch(engine->translate_input->get_color_model()) - { - case BC_RGB888: - TRANSLATE(0xff, unsigned char, 3, 0); - break; - - case BC_RGBA8888: - TRANSLATE(0xff, unsigned char, 4, 0); - break; - - case BC_RGB161616: - TRANSLATE(0xffff, uint16_t, 3, 0); - break; - - case BC_RGBA16161616: - TRANSLATE(0xffff, uint16_t, 4, 0); - break; - - case BC_YUV888: - TRANSLATE(0xff, unsigned char, 3, 1); - break; - - case BC_YUVA8888: - TRANSLATE(0xff, unsigned char, 4, 1); - break; - - case BC_YUV161616: - TRANSLATE(0xffff, uint16_t, 3, 1); - break; - - case BC_YUVA16161616: - TRANSLATE(0xffff, uint16_t, 4, 1); - break; - } - - delete [] x_table; - delete [] y_table; -} - - - - - - - - - - -TranslateEngine::TranslateEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -TranslateEngine::~TranslateEngine() -{ -} - -void TranslateEngine::init_packages() -{ - int out_y1_int = (int)translate_out_y1; - int out_y2_int = MIN((int)ceil(translate_out_y2), translate_output->get_h()); - int out_h = out_y2_int - out_y1_int; - - for(int i = 0; i < total_packages; i++) - { - TranslatePackage *package = (TranslatePackage*)packages[i]; - package->out_row1 = (int)(out_y1_int + out_h / - total_packages * - i); - package->out_row2 = (int)((float)package->out_row1 + - out_h / - total_packages); - if(i >= total_packages - 1) - package->out_row2 = out_y2_int; - } -} - -LoadClient* TranslateEngine::new_client() -{ - return new TranslateUnit(this, overlay); -} - -LoadPackage* TranslateEngine::new_package() -{ - return new TranslatePackage; -} - - - - - - - - -#define SCALE_TRANSLATE(max, type, components) \ -{ \ - int64_t opacity = (int)(alpha * max + 0.5); \ - int64_t transparency = max - opacity; \ - int out_w = out_x2 - out_x1; \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) \ - { \ - int in_y = y_table[i - out_y1]; \ - type *in_row = (type*)in_rows[in_y] + in_x1 * components; \ - type *out_row = (type*)out_rows[i] + out_x1 * components; \ - \ -/* X direction is scaled and requires a table lookup */ \ - if(out_w != in_x2 - in_x1) \ - { \ - for(int j = 0; j < out_w; j++) \ - { \ - int in_x = x_table[j]; \ - int input1, input2, input3, input4; \ - type *output = out_row + j * components; \ - \ - input1 = in_row[in_x * components]; \ - input2 = in_row[in_x * components + 1]; \ - input3 = in_row[in_x * components + 2]; \ - if(components == 4) \ - input4 = in_row[in_x * components + 3]; \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - } \ - } \ - else \ -/* X direction is not scaled */ \ - { \ - for(int j = 0; j < out_w; j++) \ - { \ - int input1, input2, input3, input4; \ - type *output = out_row + j * components; \ - \ - input1 = in_row[j * components]; \ - input2 = in_row[j * components + 1]; \ - input3 = in_row[j * components + 2]; \ - if(components == 4) \ - input4 = in_row[j * components + 3]; \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - } \ - } \ - } \ -} - - - -ScaleTranslateUnit::ScaleTranslateUnit(ScaleTranslateEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; - this->scale_translate = server; -} - -ScaleTranslateUnit::~ScaleTranslateUnit() -{ -} - -void ScaleTranslateUnit::scale_array(int* &table, - int out_x1, - int out_x2, - int in_x1, - int in_x2, - int is_x) -{ - float scale = (float)(out_x2 - out_x1) / (in_x2 - in_x1); - - table = new int[out_x2 - out_x1]; - - if(!is_x) - { - for(int i = 0; i < out_x2 - out_x1; i++) - { - table[i] = (int)((float)i / scale + in_x1); - } - } - else - { - for(int i = 0; i < out_x2 - out_x1; i++) - { - table[i] = (int)((float)i / scale); - } - } -} - - -void ScaleTranslateUnit::process_package(LoadPackage *package) -{ - ScaleTranslatePackage *pkg = (ScaleTranslatePackage*)package; - -// Args for NEAREST_NEIGHBOR_MACRO - VFrame *output = scale_translate->output; - VFrame *input = scale_translate->input; - int in_x1 = scale_translate->in_x1; - int in_y1 = scale_translate->in_y1; - int in_x2 = scale_translate->in_x2; - int in_y2 = scale_translate->in_y2; - int out_x1 = scale_translate->out_x1; - int out_y1 = scale_translate->out_y1; - int out_x2 = scale_translate->out_x2; - int out_y2 = scale_translate->out_y2; - float alpha = scale_translate->alpha; - int mode = scale_translate->mode; - - int *x_table; - int *y_table; - unsigned char **in_rows = input->get_rows(); - unsigned char **out_rows = output->get_rows(); - - scale_array(x_table, - out_x1, - out_x2, - in_x1, - in_x2, - 1); - scale_array(y_table, - out_y1, - out_y2, - in_y1, - in_y2, - 0); - - - switch(input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - SCALE_TRANSLATE(0xff, uint8_t, 3); - break; - - case BC_RGBA8888: - case BC_YUVA8888: - SCALE_TRANSLATE(0xff, uint8_t, 4); - break; - - - case BC_RGB161616: - case BC_YUV161616: - SCALE_TRANSLATE(0xffff, uint16_t, 3); - break; - - case BC_RGBA16161616: - case BC_YUVA16161616: - SCALE_TRANSLATE(0xffff, uint16_t, 4); - break; - } - - delete [] x_table; - delete [] y_table; - -}; - - - - - - - - - -ScaleTranslateEngine::ScaleTranslateEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -ScaleTranslateEngine::~ScaleTranslateEngine() -{ -} - -void ScaleTranslateEngine::init_packages() -{ - int out_h = out_y2 - out_y1; - - for(int i = 0; i < total_packages; i++) - { - ScaleTranslatePackage *package = (ScaleTranslatePackage*)packages[i]; - package->out_row1 = (int)(out_y1 + out_h / - total_packages * - i); - package->out_row2 = (int)((float)package->out_row1 + - out_h / - total_packages); - if(i >= total_packages - 1) - package->out_row2 = out_y2; - } -} - -LoadClient* ScaleTranslateEngine::new_client() -{ - return new ScaleTranslateUnit(this, overlay); -} - -LoadPackage* ScaleTranslateEngine::new_package() -{ - return new ScaleTranslatePackage; -} - - -ScaleTranslatePackage::ScaleTranslatePackage() -{ -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define BLEND_ONLY(type, max, components) \ -{ \ - int64_t opacity = (int)(alpha * max + 0.5); \ - int64_t transparency = max - opacity; \ - \ - type** output_rows = (type**)output->get_rows(); \ - type** input_rows = (type**)input->get_rows(); \ - int w = input->get_w(); \ - int h = input->get_h(); \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) \ - { \ - type* in_row = input_rows[i]; \ - type* output = output_rows[i]; \ - \ - for(int j = 0; j < w; j++) \ - { \ - int input1, input2, input3, input4; \ - input1 = in_row[j * components]; \ - input2 = in_row[j * components + 1]; \ - input3 = in_row[j * components + 2]; \ - if(components == 4) input4 = in_row[j * components + 3]; \ - \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - \ - input += components; \ - output += components; \ - } \ - } \ -} - - - - -BlendUnit::BlendUnit(BlendEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; - this->blend_engine = server; -} - -BlendUnit::~BlendUnit() -{ -} - -void BlendUnit::process_package(LoadPackage *package) -{ - BlendPackage *pkg = (BlendPackage*)package; - - - VFrame *output = blend_engine->output; - VFrame *input = blend_engine->input; - float alpha = blend_engine->alpha; - int mode = blend_engine->mode; - - switch(input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - BLEND_ONLY(unsigned char, 0xff, 3); - break; - case BC_RGBA8888: - case BC_YUVA8888: - BLEND_ONLY(unsigned char, 0xff, 4); - break; - case BC_RGB161616: - case BC_YUV161616: - BLEND_ONLY(uint16_t, 0xffff, 3); - break; - case BC_RGBA16161616: - case BC_YUVA16161616: - BLEND_ONLY(uint16_t, 0xffff, 4); - break; - } -} - - - -BlendEngine::BlendEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -BlendEngine::~BlendEngine() -{ -} - -void BlendEngine::init_packages() -{ - for(int i = 0; i < total_packages; i++) - { - BlendPackage *package = (BlendPackage*)packages[i]; - package->out_row1 = (int)(input->get_h() / - total_packages * - i); - package->out_row2 = (int)((float)package->out_row1 + - input->get_h() / - total_packages); - - if(i >= total_packages - 1) - package->out_row2 = input->get_h(); - } -} - -LoadClient* BlendEngine::new_client() -{ - return new BlendUnit(this, overlay); -} - -LoadPackage* BlendEngine::new_package() -{ - return new BlendPackage; -} - - -BlendPackage::BlendPackage() -{ -} - - diff --git a/cinelerra-5.1/cinelerra/overlayframe.C.float b/cinelerra-5.1/cinelerra/overlayframe.C.float deleted file mode 100644 index 24c77812..00000000 --- a/cinelerra-5.1/cinelerra/overlayframe.C.float +++ /dev/null @@ -1,1723 +0,0 @@ -#include -#include -#include -#include - -#include "clip.h" -#include "edl.inc" -#include "overlayframe.h" -#include "vframe.h" - -OverlayFrame::OverlayFrame(int cpus) -{ - temp_frame = 0; - blend_engine = 0; - scale_engine = 0; - scaletranslate_engine = 0; - translate_engine = 0; - this->cpus = cpus; -} - -OverlayFrame::~OverlayFrame() -{ -//printf("OverlayFrame::~OverlayFrame 1\n"); - if(temp_frame) delete temp_frame; - if(scale_engine) delete scale_engine; - if(translate_engine) delete translate_engine; - if(blend_engine) delete blend_engine; - if(scaletranslate_engine) delete scaletranslate_engine; -//printf("OverlayFrame::~OverlayFrame 2\n"); -} - - - - - - - - -// Verification: - -// (255 * 255 + 0 * 0) / 255 = 255 -// (255 * 127 + 255 * (255 - 127)) / 255 = 255 - -// (65535 * 65535 + 0 * 0) / 65535 = 65535 -// (65535 * 32767 + 65535 * (65535 - 32767)) / 65535 = 65535 - - -// Branch prediction 4 U - -#define BLEND_3(max, type) \ -{ \ - int64_t r, g, b; \ - \ -/* if(mode != TRANSFER_NORMAL) printf("BLEND mode = %d\n", mode); */ \ - switch(mode) \ - { \ - case TRANSFER_DIVIDE: \ - r = output[0] ? (((int64_t)input1 * max) / output[0]) : max; \ - g = output[1] ? (((int64_t)input2 * max) / output[1]) : max; \ - b = output[2] ? (((int64_t)input3 * max) / output[2]) : max; \ - r = (r * opacity + output[0] * transparency) / max; \ - g = (g * opacity + output[1] * transparency) / max; \ - b = (b * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_MULTIPLY: \ - r = ((int64_t)input1 * output[0]) / max; \ - g = ((int64_t)input2 * output[1]) / max; \ - b = ((int64_t)input3 * output[2]) / max; \ - r = (r * opacity + output[0] * transparency) / max; \ - g = (g * opacity + output[1] * transparency) / max; \ - b = (b * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_SUBTRACT: \ - r = (((int64_t)input1 - output[0]) * opacity + output[0] * transparency) / max; \ - g = (((int64_t)input2 - output[1]) * opacity + output[1] * transparency) / max; \ - b = (((int64_t)input3 - output[2]) * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_ADDITION: \ - r = (((int64_t)input1 + output[0]) * opacity + output[0] * transparency) / max; \ - g = (((int64_t)input2 + output[1]) * opacity + output[1] * transparency) / max; \ - b = (((int64_t)input3 + output[2]) * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_REPLACE: \ - r = input1; \ - g = input2; \ - b = input3; \ - break; \ - case TRANSFER_NORMAL: \ - r = ((int64_t)input1 * opacity + output[0] * transparency) / max; \ - g = ((int64_t)input2 * opacity + output[1] * transparency) / max; \ - b = ((int64_t)input3 * opacity + output[2] * transparency) / max; \ - break; \ - } \ - \ - output[0] = (type)CLIP(r, 0, max); \ - output[1] = (type)CLIP(g, 0, max); \ - output[2] = (type)CLIP(b, 0, max); \ -} - - - - - -// Blending equations are drastically different for 3 and 4 components -#define BLEND_4(max, type) \ -{ \ - int64_t r, g, b, a; \ - int64_t pixel_opacity, pixel_transparency; \ - \ - pixel_opacity = opacity * input4 / max; \ - pixel_transparency = (max - pixel_opacity) * output[3] / max; \ - \ - switch(mode) \ - { \ - case TRANSFER_DIVIDE: \ - r = output[0] ? (((int64_t)input1 * max) / output[0]) : max; \ - g = output[1] ? (((int64_t)input2 * max) / output[1]) : max; \ - b = output[2] ? (((int64_t)input3 * max) / output[2]) : max; \ - r = (r * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (g * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (b * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_MULTIPLY: \ - r = ((int64_t)input1 * output[0]) / max; \ - g = ((int64_t)input2 * output[1]) / max; \ - b = ((int64_t)input3 * output[2]) / max; \ - r = (r * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (g * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (b * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_SUBTRACT: \ - r = (((int64_t)input1 - output[0]) * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (((int64_t)input2 - output[1]) * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (((int64_t)input3 - output[2]) * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_ADDITION: \ - r = (((int64_t)input1 + output[0]) * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (((int64_t)input2 + output[1]) * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (((int64_t)input3 + output[2]) * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_REPLACE: \ - r = input1; \ - g = input2; \ - b = input3; \ - a = input4; \ - break; \ - case TRANSFER_NORMAL: \ - r = ((int64_t)input1 * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = ((int64_t)input2 * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = ((int64_t)input3 * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - } \ - \ - output[0] = (type)CLIP(r, 0, max); \ - output[1] = (type)CLIP(g, 0, max); \ - output[2] = (type)CLIP(b, 0, max); \ - output[3] = (type)a; \ -} - - - - - - - - -// Bicubic algorithm using multiprocessors -// input -> scale nearest integer boundaries -> temp -> translation -> blend -> output - -// Nearest neighbor algorithm using multiprocessors for blending -// input -> scale + translate -> blend -> output - - -int OverlayFrame::overlay(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, // 0 - 1 - int mode, - int interpolation_type) -{ - float w_scale = (out_x2 - out_x1) / (in_x2 - in_x1); - float h_scale = (out_y2 - out_y1) / (in_y2 - in_y1); - -//printf("OverlayFrame::overlay 1 %d %f\n", mode, alpha); -// Limit values - if(in_x1 < 0) - { - out_x1 += -in_x1 * w_scale; - in_x1 = 0; - } - else - if(in_x1 >= input->get_w()) - { - out_x1 -= (in_x1 - input->get_w()) * w_scale; - in_x1 = input->get_w(); - } - - if(in_y1 < 0) - { - out_y1 += -in_y1 * h_scale; - in_y1 = 0; - } - else - if(in_y1 >= input->get_h()) - { - out_y1 -= (in_y1 - input->get_h()) * h_scale; - in_y1 = input->get_h(); - } - - if(in_x2 < 0) - { - out_x2 += -in_x2 * w_scale; - in_x2 = 0; - } - else - if(in_x2 >= input->get_w()) - { - out_x2 -= (in_x2 - input->get_w()) * w_scale; - in_x2 = input->get_w(); - } - - if(in_y2 < 0) - { - out_y2 += -in_y2 * h_scale; - in_y2 = 0; - } - else - if(in_y2 >= input->get_h()) - { - out_y2 -= (in_y2 - input->get_h()) * h_scale; - in_y2 = input->get_h(); - } - - if(out_x1 < 0) - { - in_x1 += -out_x1 / w_scale; - out_x1 = 0; - } - else - if(out_x1 >= output->get_w()) - { - in_x1 -= (out_x1 - output->get_w()) / w_scale; - out_x1 = output->get_w(); - } - - if(out_y1 < 0) - { - in_y1 += -out_y1 / h_scale; - out_y1 = 0; - } - else - if(out_y1 >= output->get_h()) - { - in_y1 -= (out_y1 - output->get_h()) / h_scale; - out_y1 = output->get_h(); - } - - if(out_x2 < 0) - { - in_x2 += -out_x2 / w_scale; - out_x2 = 0; - } - else - if(out_x2 >= output->get_w()) - { - in_x2 -= (out_x2 - output->get_w()) / w_scale; - out_x2 = output->get_w(); - } - - if(out_y2 < 0) - { - in_y2 += -out_y2 / h_scale; - out_y2 = 0; - } - else - if(out_y2 >= output->get_h()) - { - in_y2 -= (out_y2 - output->get_h()) / h_scale; - out_y2 = output->get_h(); - } - - - - - - float in_w = in_x2 - in_x1; - float in_h = in_y2 - in_y1; - float out_w = out_x2 - out_x1; - float out_h = out_y2 - out_y1; -// Input for translation operation - VFrame *translation_input = input; - - - -// printf("OverlayFrame::overlay %f %f %f %f -> %f %f %f %f\n", in_x1, -// in_y1, -// in_x2, -// in_y2, -// out_x1, -// out_y1, -// out_x2, -// out_y2); - - - - - -// **************************************************************************** -// Transfer to temp buffer by scaling nearest integer boundaries -// **************************************************************************** - if(interpolation_type != NEAREST_NEIGHBOR && - (!EQUIV(w_scale, 1) || !EQUIV(h_scale, 1))) - { -// Create integer boundaries for interpolation - int in_x1_int = (int)in_x1; - int in_y1_int = (int)in_y1; - int in_x2_int = MIN((int)ceil(in_x2), input->get_w()); - int in_y2_int = MIN((int)ceil(in_y2), input->get_h()); - -// Dimensions of temp frame. Integer boundaries scaled. - int temp_w = (int)ceil(w_scale * (in_x2_int - in_x1_int)); - int temp_h = (int)ceil(h_scale * (in_y2_int - in_y1_int)); - VFrame *scale_output; - - - -#define NO_TRANSLATION1 \ - (EQUIV(in_x1, 0) && \ - EQUIV(in_y1, 0) && \ - EQUIV(out_x1, 0) && \ - EQUIV(out_y1, 0) && \ - EQUIV(in_x2, in_x2_int) && \ - EQUIV(in_y2, in_y2_int) && \ - EQUIV(out_x2, temp_w) && \ - EQUIV(out_y2, temp_h)) - - -#define NO_BLEND \ - (EQUIV(alpha, 1) && \ - (mode == TRANSFER_REPLACE || \ - (mode == TRANSFER_NORMAL && cmodel_components(input->get_color_model()) == 3))) - - - - - -// Prepare destination for operation - -// No translation and no blending. The blending operation is built into the -// translation unit but not the scaling unit. -// input -> output - if(NO_TRANSLATION1 && - NO_BLEND) - { -// printf("OverlayFrame::overlay input -> output\n"); - - scale_output = output; - translation_input = 0; - } - else -// If translation or blending -// input -> nearest integer boundary temp - { - if(temp_frame && - (temp_frame->get_w() != temp_w || - temp_frame->get_h() != temp_h)) - { - delete temp_frame; - temp_frame = 0; - } - - if(!temp_frame) - { - temp_frame = new VFrame(0, - temp_w, - temp_h, - input->get_color_model(), - -1); - } -//printf("OverlayFrame::overlay input -> temp\n"); - - - temp_frame->clear_frame(); - -// printf("OverlayFrame::overlay 4 temp_w=%d temp_h=%d\n", -// temp_w, temp_h); - scale_output = temp_frame; - translation_input = scale_output; - -// Adjust input coordinates to reflect new scaled coordinates. - in_x1 = (in_x1 - in_x1_int) * w_scale; - in_y1 = (in_y1 - in_y1_int) * h_scale; - in_x2 = (in_x2 - in_x1_int) * w_scale; - in_y2 = (in_y2 - in_y1_int) * h_scale; - } - - - - -// Scale input -> scale_output - this->scale_output = scale_output; - this->scale_input = input; - this->w_scale = w_scale; - this->h_scale = h_scale; - this->in_x1_int = in_x1_int; - this->in_y1_int = in_y1_int; - this->out_w_int = temp_w; - this->out_h_int = temp_h; - this->interpolation_type = interpolation_type; - -//printf("OverlayFrame::overlay ScaleEngine 1 %d\n", out_h_int); - if(!scale_engine) scale_engine = new ScaleEngine(this, cpus); - scale_engine->process_packages(); -//printf("OverlayFrame::overlay ScaleEngine 2\n"); - - - - } - -// printf("OverlayFrame::overlay 1 %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", -// in_x1, -// in_y1, -// in_x2, -// in_y2, -// out_x1, -// out_y1, -// out_x2, -// out_y2); - - - - - -#define NO_TRANSLATION2 \ - (EQUIV(in_x1, 0) && \ - EQUIV(in_y1, 0) && \ - EQUIV(in_x2, translation_input->get_w()) && \ - EQUIV(in_y2, translation_input->get_h()) && \ - EQUIV(out_x1, 0) && \ - EQUIV(out_y1, 0) && \ - EQUIV(out_x2, output->get_w()) && \ - EQUIV(out_y2, output->get_h())) \ - -#define NO_SCALE \ - (EQUIV(out_x2 - out_x1, in_x2 - in_x1) && \ - EQUIV(out_y2 - out_y1, in_y2 - in_y1)) - - - - -//printf("OverlayFrame::overlay 4 %d\n", mode); - - - - - if(translation_input) - { -// Direct copy - if( NO_TRANSLATION2 && - NO_SCALE && - NO_BLEND) - { -//printf("OverlayFrame::overlay direct copy\n"); - output->copy_from(translation_input); - } - else -// Blend only - if( NO_TRANSLATION2 && - NO_SCALE) - { - if(!blend_engine) blend_engine = new BlendEngine(this, cpus); - - - blend_engine->output = output; - blend_engine->input = translation_input; - blend_engine->alpha = alpha; - blend_engine->mode = mode; - - blend_engine->process_packages(); - } - else -// Scale and translate using nearest neighbor -// Translation is exactly on integer boundaries - if(interpolation_type == NEAREST_NEIGHBOR || - EQUIV(in_x1, (int)in_x1) && - EQUIV(in_y1, (int)in_y1) && - EQUIV(in_x2, (int)in_x2) && - EQUIV(in_y2, (int)in_y2) && - - EQUIV(out_x1, (int)out_x1) && - EQUIV(out_y1, (int)out_y1) && - EQUIV(out_x2, (int)out_x2) && - EQUIV(out_y2, (int)out_y2)) - { -//printf("OverlayFrame::overlay NEAREST_NEIGHBOR 1\n"); - if(!scaletranslate_engine) scaletranslate_engine = new ScaleTranslateEngine(this, cpus); - - - scaletranslate_engine->output = output; - scaletranslate_engine->input = translation_input; - scaletranslate_engine->in_x1 = (int)in_x1; - scaletranslate_engine->in_y1 = (int)in_y1; - scaletranslate_engine->in_x2 = (int)in_x2; - scaletranslate_engine->in_y2 = (int)in_y2; - scaletranslate_engine->out_x1 = (int)out_x1; - scaletranslate_engine->out_y1 = (int)out_y1; - scaletranslate_engine->out_x2 = (int)out_x2; - scaletranslate_engine->out_y2 = (int)out_y2; - scaletranslate_engine->alpha = alpha; - scaletranslate_engine->mode = mode; - - scaletranslate_engine->process_packages(); - } - else -// Fractional translation - { -// Use fractional translation -// printf("OverlayFrame::overlay temp -> output %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", -// in_x1, -// in_y1, -// in_x2, -// in_y2, -// out_x1, -// out_y1, -// out_x2, -// out_y2); - this->translate_output = output; - this->translate_input = translation_input; - this->translate_in_x1 = in_x1; - this->translate_in_y1 = in_y1; - this->translate_in_x2 = in_x2; - this->translate_in_y2 = in_y2; - this->translate_out_x1 = out_x1; - this->translate_out_y1 = out_y1; - this->translate_out_x2 = out_x2; - this->translate_out_y2 = out_y2; - this->translate_alpha = alpha; - this->translate_mode = mode; - -//printf("OverlayFrame::overlay 5 %d\n", mode); - if(!translate_engine) translate_engine = new TranslateEngine(this, cpus); - translate_engine->process_packages(); - - } - } -//printf("OverlayFrame::overlay 2\n"); - - return 0; -} - - - - - - - -ScalePackage::ScalePackage() -{ -} - - - - -ScaleUnit::ScaleUnit(ScaleEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; -} - -ScaleUnit::~ScaleUnit() -{ -} - - - -#define BILINEAR(max, type, components) \ -{ \ - float k_y = 1.0 / scale_h; \ - float k_x = 1.0 / scale_w; \ - type **in_rows = (type**)input->get_rows(); \ - type **out_rows = (type**)output->get_rows(); \ - type zero_r, zero_g, zero_b, zero_a; \ - int in_h_int = input->get_h(); \ - int in_w_int = input->get_w(); \ - \ - zero_r = 0; \ - zero_g = ((max + 1) >> 1) * (do_yuv); \ - zero_b = ((max + 1) >> 1) * (do_yuv); \ - if(components == 4) zero_a = 0; \ - \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) \ - { \ - float f_y = (float)i * k_y; \ - int i_y = (int)floor(f_y); \ - float a = f_y - floor(f_y); \ - type *in_row1 = in_rows[i_y + in_y1_int]; \ - type *in_row2 = (i_y + in_y1_int < in_h_int - 1) ? \ - in_rows[i_y + in_y1_int + 1] : \ - 0; \ - type *out_row = out_rows[i]; \ - \ - for(int j = 0; j < out_w_int; j++) \ - { \ - float f_x = (float)j * k_x; \ - int i_x = (int)floor(f_x); \ - float b = f_x - floor(f_x); \ - int x = i_x + in_x1_int; \ - float output1r, output1g, output1b, output1a; \ - float output2r, output2g, output2b, output2a; \ - float output3r, output3g, output3b, output3a; \ - float output4r, output4g, output4b, output4a; \ - \ - output1r = in_row1[x * components]; \ - output1g = in_row1[x * components + 1]; \ - output1b = in_row1[x * components + 2]; \ - if(components == 4) output1a = in_row1[x * components + 3]; \ - \ - if(x < in_w_int - 1) \ - { \ - output2r = in_row1[x * components + components]; \ - output2g = in_row1[x * components + components + 1]; \ - output2b = in_row1[x * components + components + 2]; \ - if(components == 4) output2a = in_row1[x * components + components + 3]; \ - \ - if(in_row2) \ - { \ - output4r = in_row2[x * components + components]; \ - output4g = in_row2[x * components + components + 1]; \ - output4b = in_row2[x * components + components + 2]; \ - if(components == 4) output4a = in_row2[x * components + components + 3]; \ - } \ - else \ - { \ - output4r = zero_r; \ - output4g = zero_g; \ - output4b = zero_b; \ - if(components == 4) output4a = zero_a; \ - } \ - } \ - else \ - { \ - output2r = zero_r; \ - output2g = zero_g; \ - output2b = zero_b; \ - if(components == 4) output2a = zero_a; \ - output4r = zero_r; \ - output4g = zero_g; \ - output4b = zero_b; \ - if(components == 4) output4a = zero_a; \ - } \ - \ - if(in_row2) \ - { \ - output3r = in_row2[x * components]; \ - output3g = in_row2[x * components + 1]; \ - output3b = in_row2[x * components + 2]; \ - if(components == 4) output3a = in_row2[x * components + 3]; \ - } \ - else \ - { \ - output3r = zero_r; \ - output3g = zero_g; \ - output3b = zero_b; \ - if(components == 4) output3a = zero_a; \ - } \ - \ - float anti_a = 1.0F - a; \ - float anti_b = 1.0F - b; \ - out_row[j * components] = \ - (type)((anti_a) * (((anti_b) * output1r) + \ - (b * output2r)) + \ - a * (((anti_b) * output3r) + \ - (b * output4r))); \ - out_row[j * components + 1] = \ - (type)((anti_a) * (((anti_b) * output1g) + \ - (b * output2g)) + \ - a * (((anti_b) * output3g) + \ - (b * output4g))); \ - out_row[j * components + 2] = \ - (type)((anti_a) * (((anti_b) * output1b) + \ - (b * output2b)) + \ - a * (((anti_b) * output3b) + \ - (b * output4b))); \ - if(components == 4) \ - out_row[j * components + 3] = \ - (type)((anti_a) * (((anti_b) * output1a) + \ - (b * output2a)) + \ - a * (((anti_b) * output3a) + \ - (b * output4a))); \ - } \ - } \ - \ - \ -} - - -#define BICUBIC(max, type, components) \ -{ \ - float k_y = 1.0 / scale_h; \ - float k_x = 1.0 / scale_w; \ - type **in_rows = (type**)input->get_rows(); \ - type **out_rows = (type**)output->get_rows(); \ - float *bspline_x, *bspline_y; \ - int in_h_int = input->get_h(); \ - int in_w_int = input->get_w(); \ - type zero_r, zero_g, zero_b, zero_a; \ - \ - zero_r = 0; \ - zero_b = ((max + 1) >> 1) * (do_yuv); \ - zero_g = ((max + 1) >> 1) * (do_yuv); \ - if(components == 4) \ - zero_a = 0; \ - \ - tabulate_bspline(bspline_x, \ - k_x, \ - out_w_int, \ - -1); \ - \ - tabulate_bspline(bspline_y, \ - k_y, \ - out_h_int, \ - 1); \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) \ - { \ - float f_y = (float)i * k_y; \ - int i_y = (int)floor(f_y); \ - float a = f_y - floor(f_y); \ - \ - \ - for(int j = 0; j < out_w_int; j++) \ - { \ - float f_x = (float)j * k_x; \ - int i_x = (int)floor(f_x); \ - float b = f_x - floor(f_x); \ - float output1, output2, output3, output4; \ - output1 = 0; \ - output2 = 0; \ - output3 = 0; \ - if(components == 4) \ - output4 = 0; \ - int table_y = i * 4; \ - \ -/* Kernel */ \ - for(int m = -1; m < 3; m++) \ - { \ - float r1 = bspline_y[table_y++]; \ - int y = in_y1_int + i_y + m; \ - int table_x = j * 4; \ - \ - for(int n = -1; n < 3; n++) \ - { \ - float r2 = bspline_x[table_x++]; \ - int x = in_x1_int + i_x + n; \ - float r_square = r1 * r2; \ - \ -/* Inside boundary. */ \ - if(x >= 0 && \ - x < in_w_int && \ - y >= 0 && \ - y < in_h_int) \ - { \ - output1 += r_square * in_rows[y][x * components]; \ - output2 += r_square * in_rows[y][x * components + 1]; \ - output3 += r_square * in_rows[y][x * components + 2]; \ - if(components == 4) \ - output4 += r_square * in_rows[y][x * components + 3]; \ - } \ - else \ - { \ - output1 += r_square * zero_r; \ - output2 += r_square * zero_g; \ - output3 += r_square * zero_b; \ - if(components == 4) \ - output4 += r_square * zero_a; \ - } \ - } \ - } \ - \ - \ - out_rows[i][j * components] = (type)output1; \ - out_rows[i][j * components + 1] = (type)output2; \ - out_rows[i][j * components + 2] = (type)output3; \ - if(components == 4) \ - out_rows[i][j * components + 3] = (type)output4; \ - \ - } \ - } \ - \ - delete [] bspline_x; \ - delete [] bspline_y; \ -} - - - -// Pow function is not thread safe in Compaqt C -#define CUBE(x) ((x) * (x) * (x)) - -float ScaleUnit::cubic_bspline(float x) -{ - float a, b, c, d; - - if((x + 2.0F) <= 0.0F) - { - a = 0.0F; - } - else - { - a = CUBE(x + 2.0F); - } - - - if((x + 1.0F) <= 0.0F) - { - b = 0.0F; - } - else - { - b = CUBE(x + 1.0F); - } - - if(x <= 0) - { - c = 0.0F; - } - else - { - c = CUBE(x); - } - - if((x - 1.0F) <= 0.0F) - { - d = 0.0F; - } - else - { - d = CUBE(x - 1.0F); - } - - return (a - (4.0F * b) + (6.0F * c) - (4.0F * d)) / 6.0; -} - - -void ScaleUnit::tabulate_bspline(float* &table, - float scale, - int pixels, - float coefficient) -{ - table = new float[pixels * 4]; - - for(int i = 0, j = 0; i < pixels; i++) - { - float f_x = (float)i * scale; - float a = f_x - floor(f_x); - - for(float m = -1; m < 3; m++) - { - table[j++] = cubic_bspline(coefficient * (m - a)); - } - } -} - -void ScaleUnit::process_package(LoadPackage *package) -{ - ScalePackage *pkg = (ScalePackage*)package; - -// Arguments for macros - VFrame *output = overlay->scale_output; - VFrame *input = overlay->scale_input; - float scale_w = overlay->w_scale; - float scale_h = overlay->h_scale; - int in_x1_int = overlay->in_x1_int; - int in_y1_int = overlay->in_y1_int; - int out_h_int = overlay->out_h_int; - int out_w_int = overlay->out_w_int; - int do_yuv = - (overlay->scale_input->get_color_model() == BC_YUV888 || - overlay->scale_input->get_color_model() == BC_YUVA8888 || - overlay->scale_input->get_color_model() == BC_YUV161616 || - overlay->scale_input->get_color_model() == BC_YUVA16161616); - - if(overlay->interpolation_type == CUBIC_CUBIC || - (overlay->interpolation_type == CUBIC_LINEAR - && overlay->w_scale > 1 && - overlay->h_scale > 1)) - { - - switch(overlay->scale_input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - BICUBIC(0xff, unsigned char, 3); - break; - - case BC_RGBA8888: - case BC_YUVA8888: - BICUBIC(0xff, unsigned char, 4); - break; - - case BC_RGB161616: - case BC_YUV161616: - BICUBIC(0xffff, uint16_t, 3); - break; - - case BC_RGBA16161616: - case BC_YUVA16161616: - BICUBIC(0xffff, uint16_t, 4); - break; - } - } - else -// Perform bilinear scaling input -> scale_output - { - switch(overlay->scale_input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - BILINEAR(0xff, unsigned char, 3); - break; - - case BC_RGBA8888: - case BC_YUVA8888: - BILINEAR(0xff, unsigned char, 4); - break; - - case BC_RGB161616: - case BC_YUV161616: - BILINEAR(0xffff, uint16_t, 3); - break; - - case BC_RGBA16161616: - case BC_YUVA16161616: - BILINEAR(0xffff, uint16_t, 4); - break; - } - } - -} - - - - - - - - - - - - - -ScaleEngine::ScaleEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -ScaleEngine::~ScaleEngine() -{ -} - -void ScaleEngine::init_packages() -{ - for(int i = 0; i < total_packages; i++) - { - ScalePackage *package = (ScalePackage*)packages[i]; - package->out_row1 = overlay->out_h_int / total_packages * i; - package->out_row2 = package->out_row1 + overlay->out_h_int / total_packages; - - if(i >= total_packages - 1) - package->out_row2 = overlay->out_h_int; - } -} - -LoadClient* ScaleEngine::new_client() -{ - return new ScaleUnit(this, overlay); -} - -LoadPackage* ScaleEngine::new_package() -{ - return new ScalePackage; -} - - - - - - - - - - - - - -TranslatePackage::TranslatePackage() -{ -} - - - -TranslateUnit::TranslateUnit(TranslateEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; -} - -TranslateUnit::~TranslateUnit() -{ -} - - - -void TranslateUnit::translation_array(transfer_table* &table, - float out_x1, - float out_x2, - float in_x1, - float in_x2, - int in_total, - int out_total, - int &out_x1_int, - int &out_x2_int) -{ - int out_w_int; - float offset = out_x1 - in_x1; - - out_x1_int = (int)out_x1; - out_x2_int = MIN((int)ceil(out_x2), out_total); - out_w_int = out_x2_int - out_x1_int; - - table = new transfer_table[out_w_int]; - bzero(table, sizeof(transfer_table) * out_w_int); - - -//printf("OverlayFrame::translation_array 1 %f %f -> %f %f\n", in_x1, in_x2, out_x1, out_x2); - - float in_x = in_x1; - for(int out_x = out_x1_int; out_x < out_x2_int; out_x++) - { - transfer_table *entry = &table[out_x - out_x1_int]; - - entry->in_x1 = (int)in_x; - entry->in_x2 = (int)in_x + 1; - -// Get fraction of output pixel to fill - entry->output_fraction = 1; - - if(out_x1 > out_x) - { - entry->output_fraction -= out_x1 - out_x; - } - - if(out_x2 < out_x + 1) - { - entry->output_fraction = (out_x2 - out_x); - } - -// Advance in_x until out_x_fraction is filled - float out_x_fraction = entry->output_fraction; - float in_x_fraction = floor(in_x + 1) - in_x; - - if(out_x_fraction <= in_x_fraction) - { - entry->in_fraction1 = out_x_fraction; - entry->in_fraction2 = 0.0; - in_x += out_x_fraction; - } - else - { - entry->in_fraction1 = in_x_fraction; - in_x += out_x_fraction; - entry->in_fraction2 = in_x - floor(in_x); - } - -// Clip in_x - if(entry->in_x2 >= in_total) - { - entry->in_x2 = in_total - 1; - entry->in_fraction2 = 0.0; - } - - if(entry->in_x1 >= in_total) - { - entry->in_x1 = in_total - 1; - entry->in_fraction1 = 0.0; - } -// printf("OverlayFrame::translation_array 2 %d %d %d %f %f %f\n", -// out_x, -// entry->in_x1, -// entry->in_x2, -// entry->in_fraction1, -// entry->in_fraction2, -// entry->output_fraction); - } -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define TRANSLATE(max, type, components) \ -{ \ - \ - type **in_rows = (type**)input->get_rows(); \ - type **out_rows = (type**)output->get_rows(); \ - \ -/* printf("OverlayFrame::translate 1 %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", */ \ -/* (in_x1), in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2); */ \ - \ - unsigned int master_opacity = (int)(alpha * max + 0.5); \ - unsigned int master_transparency = max - master_opacity; \ - \ -/* printf("TRANSLATE %d\n", mode); */ \ - \ - for(int i = row1; i < row2; i++) \ - { \ - int in_y1 = y_table[i - out_y1_int].in_x1; \ - int in_y2 = y_table[i - out_y1_int].in_x2; \ - float y_fraction1 = y_table[i - out_y1_int].in_fraction1; \ - float y_fraction2 = y_table[i - out_y1_int].in_fraction2; \ - float y_output_fraction = y_table[i - out_y1_int].output_fraction; \ - type *in_row1 = in_rows[(in_y1)]; \ - type *in_row2 = in_rows[(in_y2)]; \ - type *out_row = out_rows[i]; \ - \ - for(int j = out_x1_int; j < out_x2_int; j++) \ - { \ - int in_x1 = x_table[j - out_x1_int].in_x1; \ - int in_x2 = x_table[j - out_x1_int].in_x2; \ - float x_fraction1 = x_table[j - out_x1_int].in_fraction1; \ - float x_fraction2 = x_table[j - out_x1_int].in_fraction2; \ - float x_output_fraction = x_table[j - out_x1_int].output_fraction; \ - type *output = &out_row[j * components]; \ - int input1, input2, input3, input4; \ - \ - input1 = (int)(in_row1[in_x1 * components] * x_fraction1 * y_fraction1 + \ - in_row1[in_x2 * components] * x_fraction2 * y_fraction1 + \ - in_row2[in_x1 * components] * x_fraction1 * y_fraction2 + \ - in_row2[in_x2 * components] * x_fraction2 * y_fraction2 + 0.5); \ - input2 = (int)(in_row1[in_x1 * components + 1] * x_fraction1 * y_fraction1 + \ - in_row1[in_x2 * components + 1] * x_fraction2 * y_fraction1 + \ - in_row2[in_x1 * components + 1] * x_fraction1 * y_fraction2 + \ - in_row2[in_x2 * components + 1] * x_fraction2 * y_fraction2 + 0.5); \ - input3 = (int)(in_row1[in_x1 * components + 2] * x_fraction1 * y_fraction1 + \ - in_row1[in_x2 * components + 2] * x_fraction2 * y_fraction1 + \ - in_row2[in_x1 * components + 2] * x_fraction1 * y_fraction2 + \ - in_row2[in_x2 * components + 2] * x_fraction2 * y_fraction2 + 0.5); \ - if(components == 4) \ - input4 = (int)(in_row1[in_x1 * components + 3] * x_fraction1 * y_fraction1 + \ - in_row1[in_x2 * components + 3] * x_fraction2 * y_fraction1 + \ - in_row2[in_x1 * components + 3] * x_fraction1 * y_fraction2 + \ - in_row2[in_x2 * components + 3] * x_fraction2 * y_fraction2 + 0.5); \ - \ - unsigned int opacity = (int)(master_opacity * \ - y_output_fraction * \ - x_output_fraction + 0.5); \ - unsigned int transparency = max - opacity; \ - \ -/* if(opacity != max) printf("TRANSLATE %x %d %d\n", opacity, j, i); */ \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - } \ - } \ -} - -void TranslateUnit::process_package(LoadPackage *package) -{ - TranslatePackage *pkg = (TranslatePackage*)package; - int out_y1_int; - int out_y2_int; - int out_x1_int; - int out_x2_int; - - -// Variables for TRANSLATE - VFrame *input = overlay->translate_input; - VFrame *output = overlay->translate_output; - float in_x1 = overlay->translate_in_x1; - float in_y1 = overlay->translate_in_y1; - float in_x2 = overlay->translate_in_x2; - float in_y2 = overlay->translate_in_y2; - float out_x1 = overlay->translate_out_x1; - float out_y1 = overlay->translate_out_y1; - float out_x2 = overlay->translate_out_x2; - float out_y2 = overlay->translate_out_y2; - float alpha = overlay->translate_alpha; - int row1 = pkg->out_row1; - int row2 = pkg->out_row2; - int mode = overlay->translate_mode; - - transfer_table *x_table; - transfer_table *y_table; - - translation_array(x_table, - out_x1, - out_x2, - in_x1, - in_x2, - input->get_w(), - output->get_w(), - out_x1_int, - out_x2_int); - translation_array(y_table, - out_y1, - out_y2, - in_y1, - in_y2, - input->get_h(), - output->get_h(), - out_y1_int, - out_y2_int); - - switch(overlay->translate_input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - TRANSLATE(0xff, unsigned char, 3); - break; - - case BC_RGBA8888: - case BC_YUVA8888: - TRANSLATE(0xff, unsigned char, 4); - break; - - case BC_RGB161616: - case BC_YUV161616: - TRANSLATE(0xffff, uint16_t, 3); - break; - - case BC_RGBA16161616: - case BC_YUVA16161616: - TRANSLATE(0xffff, uint16_t, 4); - break; - } - - delete [] x_table; - delete [] y_table; -} - - - - - - - - - - -TranslateEngine::TranslateEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -TranslateEngine::~TranslateEngine() -{ -} - -void TranslateEngine::init_packages() -{ - int out_y1_int = (int)overlay->translate_out_y1; - int out_y2_int = MIN((int)ceil(overlay->translate_out_y2), overlay->translate_output->get_h()); - int out_h = out_y2_int - out_y1_int; - - for(int i = 0; i < total_packages; i++) - { - TranslatePackage *package = (TranslatePackage*)packages[i]; - package->out_row1 = (int)(out_y1_int + out_h / - total_packages * - i); - package->out_row2 = (int)((float)package->out_row1 + - out_h / - total_packages); - if(i >= total_packages - 1) - package->out_row2 = out_y2_int; - } -} - -LoadClient* TranslateEngine::new_client() -{ - return new TranslateUnit(this, overlay); -} - -LoadPackage* TranslateEngine::new_package() -{ - return new TranslatePackage; -} - - - - - - - - -#define SCALE_TRANSLATE(max, type, components) \ -{ \ - int64_t opacity = (int)(alpha * max + 0.5); \ - int64_t transparency = max - opacity; \ - int out_w = out_x2 - out_x1; \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) \ - { \ - int in_y = y_table[i - out_y1]; \ - type *in_row = (type*)in_rows[in_y] + in_x1 * components; \ - type *out_row = (type*)out_rows[i] + out_x1 * components; \ - \ -/* X direction is scaled and requires a table lookup */ \ - if(out_w != in_x2 - in_x1) \ - { \ - for(int j = 0; j < out_w; j++) \ - { \ - int in_x = x_table[j]; \ - int input1, input2, input3, input4; \ - type *output = out_row + j * components; \ - \ - input1 = in_row[in_x * components]; \ - input2 = in_row[in_x * components + 1]; \ - input3 = in_row[in_x * components + 2]; \ - if(components == 4) \ - input4 = in_row[in_x * components + 3]; \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - } \ - } \ - else \ -/* X direction is not scaled */ \ - { \ - for(int j = 0; j < out_w; j++) \ - { \ - int input1, input2, input3, input4; \ - type *output = out_row + j * components; \ - \ - input1 = in_row[j * components]; \ - input2 = in_row[j * components + 1]; \ - input3 = in_row[j * components + 2]; \ - if(components == 4) \ - input4 = in_row[j * components + 3]; \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - } \ - } \ - } \ -} - - - -ScaleTranslateUnit::ScaleTranslateUnit(ScaleTranslateEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; - this->scale_translate = server; -} - -ScaleTranslateUnit::~ScaleTranslateUnit() -{ -} - -void ScaleTranslateUnit::scale_array(int* &table, - int out_x1, - int out_x2, - int in_x1, - int in_x2, - int is_x) -{ - float scale = (float)(out_x2 - out_x1) / (in_x2 - in_x1); - - table = new int[out_x2 - out_x1]; - - if(!is_x) - { - for(int i = 0; i < out_x2 - out_x1; i++) - { - table[i] = (int)((float)i / scale + in_x1); - } - } - else - { - for(int i = 0; i < out_x2 - out_x1; i++) - { - table[i] = (int)((float)i / scale); - } - } -} - - -void ScaleTranslateUnit::process_package(LoadPackage *package) -{ - ScaleTranslatePackage *pkg = (ScaleTranslatePackage*)package; - -// Args for NEAREST_NEIGHBOR_MACRO - VFrame *output = scale_translate->output; - VFrame *input = scale_translate->input; - int in_x1 = scale_translate->in_x1; - int in_y1 = scale_translate->in_y1; - int in_x2 = scale_translate->in_x2; - int in_y2 = scale_translate->in_y2; - int out_x1 = scale_translate->out_x1; - int out_y1 = scale_translate->out_y1; - int out_x2 = scale_translate->out_x2; - int out_y2 = scale_translate->out_y2; - float alpha = scale_translate->alpha; - int mode = scale_translate->mode; - - int *x_table; - int *y_table; - unsigned char **in_rows = input->get_rows(); - unsigned char **out_rows = output->get_rows(); - - scale_array(x_table, - out_x1, - out_x2, - in_x1, - in_x2, - 1); - scale_array(y_table, - out_y1, - out_y2, - in_y1, - in_y2, - 0); - - - switch(input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - SCALE_TRANSLATE(0xff, uint8_t, 3); - break; - - case BC_RGBA8888: - case BC_YUVA8888: - SCALE_TRANSLATE(0xff, uint8_t, 4); - break; - - - case BC_RGB161616: - case BC_YUV161616: - SCALE_TRANSLATE(0xffff, uint16_t, 3); - break; - - case BC_RGBA16161616: - case BC_YUVA16161616: - SCALE_TRANSLATE(0xffff, uint16_t, 4); - break; - } - - delete [] x_table; - delete [] y_table; - -}; - - - - - - - - - -ScaleTranslateEngine::ScaleTranslateEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -ScaleTranslateEngine::~ScaleTranslateEngine() -{ -} - -void ScaleTranslateEngine::init_packages() -{ - int out_h = out_y2 - out_y1; - - for(int i = 0; i < total_packages; i++) - { - ScaleTranslatePackage *package = (ScaleTranslatePackage*)packages[i]; - package->out_row1 = (int)(out_y1 + out_h / - total_packages * - i); - package->out_row2 = (int)((float)package->out_row1 + - out_h / - total_packages); - if(i >= total_packages - 1) - package->out_row2 = out_y2; - } -} - -LoadClient* ScaleTranslateEngine::new_client() -{ - return new ScaleTranslateUnit(this, overlay); -} - -LoadPackage* ScaleTranslateEngine::new_package() -{ - return new ScaleTranslatePackage; -} - - -ScaleTranslatePackage::ScaleTranslatePackage() -{ -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define BLEND_ONLY(type, max, components) \ -{ \ - int64_t opacity = (int)(alpha * max + 0.5); \ - int64_t transparency = max - opacity; \ - \ - type** output_rows = (type**)output->get_rows(); \ - type** input_rows = (type**)input->get_rows(); \ - int w = input->get_w(); \ - int h = input->get_h(); \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) \ - { \ - type* in_row = input_rows[i]; \ - type* output = output_rows[i]; \ - \ - for(int j = 0; j < w; j++) \ - { \ - int input1, input2, input3, input4; \ - input1 = in_row[j * components]; \ - input2 = in_row[j * components + 1]; \ - input3 = in_row[j * components + 2]; \ - if(components == 4) input4 = in_row[j * components + 3]; \ - \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - \ - input += components; \ - output += components; \ - } \ - } \ -} - - - - -BlendUnit::BlendUnit(BlendEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; - this->blend_engine = server; -} - -BlendUnit::~BlendUnit() -{ -} - -void BlendUnit::process_package(LoadPackage *package) -{ - BlendPackage *pkg = (BlendPackage*)package; - - - VFrame *output = blend_engine->output; - VFrame *input = blend_engine->input; - float alpha = blend_engine->alpha; - int mode = blend_engine->mode; - - switch(input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - BLEND_ONLY(unsigned char, 0xff, 3); - break; - case BC_RGBA8888: - case BC_YUVA8888: - BLEND_ONLY(unsigned char, 0xff, 4); - break; - case BC_RGB161616: - case BC_YUV161616: - BLEND_ONLY(uint16_t, 0xffff, 3); - break; - case BC_RGBA16161616: - case BC_YUVA16161616: - BLEND_ONLY(uint16_t, 0xffff, 4); - break; - } -} - - - -BlendEngine::BlendEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -BlendEngine::~BlendEngine() -{ -} - -void BlendEngine::init_packages() -{ - for(int i = 0; i < total_packages; i++) - { - BlendPackage *package = (BlendPackage*)packages[i]; - package->out_row1 = (int)(input->get_h() / - total_packages * - i); - package->out_row2 = (int)((float)package->out_row1 + - input->get_h() / - total_packages); - - if(i >= total_packages - 1) - package->out_row2 = input->get_h(); - } -} - -LoadClient* BlendEngine::new_client() -{ - return new BlendUnit(this, overlay); -} - -LoadPackage* BlendEngine::new_package() -{ - return new BlendPackage; -} - - -BlendPackage::BlendPackage() -{ -} - - diff --git a/cinelerra-5.1/cinelerra/overlayframe.C.floattable b/cinelerra-5.1/cinelerra/overlayframe.C.floattable deleted file mode 100644 index 6b01219a..00000000 --- a/cinelerra-5.1/cinelerra/overlayframe.C.floattable +++ /dev/null @@ -1,1769 +0,0 @@ -#include -#include -#include -#include - -#include "clip.h" -#include "edl.inc" -#include "mutex.h" -#include "overlayframe.h" -#include "vframe.h" - -OverlayFrame::OverlayFrame(int cpus) -{ - temp_frame = 0; - blend_engine = 0; - scale_engine = 0; - scaletranslate_engine = 0; - translate_engine = 0; - this->cpus = cpus; -} - -OverlayFrame::~OverlayFrame() -{ -//printf("OverlayFrame::~OverlayFrame 1\n"); - if(temp_frame) delete temp_frame; - if(scale_engine) delete scale_engine; - if(translate_engine) delete translate_engine; - if(blend_engine) delete blend_engine; - if(scaletranslate_engine) delete scaletranslate_engine; -//printf("OverlayFrame::~OverlayFrame 2\n"); -} - - - - - - - - -// Verification: - -// (255 * 255 + 0 * 0) / 255 = 255 -// (255 * 127 + 255 * (255 - 127)) / 255 = 255 - -// (65535 * 65535 + 0 * 0) / 65535 = 65535 -// (65535 * 32767 + 65535 * (65535 - 32767)) / 65535 = 65535 - - -// Branch prediction 4 U - -#define BLEND_3(max, type) \ -{ \ - int64_t r, g, b; \ - \ -/* if(mode != TRANSFER_NORMAL) printf("BLEND mode = %d\n", mode); */ \ - switch(mode) \ - { \ - case TRANSFER_DIVIDE: \ - r = output[0] ? (((int64_t)input1 * max) / output[0]) : max; \ - g = output[1] ? (((int64_t)input2 * max) / output[1]) : max; \ - b = output[2] ? (((int64_t)input3 * max) / output[2]) : max; \ - r = (r * opacity + output[0] * transparency) / max; \ - g = (g * opacity + output[1] * transparency) / max; \ - b = (b * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_MULTIPLY: \ - r = ((int64_t)input1 * output[0]) / max; \ - g = ((int64_t)input2 * output[1]) / max; \ - b = ((int64_t)input3 * output[2]) / max; \ - r = (r * opacity + output[0] * transparency) / max; \ - g = (g * opacity + output[1] * transparency) / max; \ - b = (b * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_SUBTRACT: \ - r = (((int64_t)input1 - output[0]) * opacity + output[0] * transparency) / max; \ - g = (((int64_t)input2 - output[1]) * opacity + output[1] * transparency) / max; \ - b = (((int64_t)input3 - output[2]) * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_ADDITION: \ - r = (((int64_t)input1 + output[0]) * opacity + output[0] * transparency) / max; \ - g = (((int64_t)input2 + output[1]) * opacity + output[1] * transparency) / max; \ - b = (((int64_t)input3 + output[2]) * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_REPLACE: \ - r = input1; \ - g = input2; \ - b = input3; \ - break; \ - case TRANSFER_NORMAL: \ - r = ((int64_t)input1 * opacity + output[0] * transparency) / max; \ - g = ((int64_t)input2 * opacity + output[1] * transparency) / max; \ - b = ((int64_t)input3 * opacity + output[2] * transparency) / max; \ - break; \ - } \ - \ - output[0] = (type)CLIP(r, 0, max); \ - output[1] = (type)CLIP(g, 0, max); \ - output[2] = (type)CLIP(b, 0, max); \ -} - - - - - -// Blending equations are drastically different for 3 and 4 components -#define BLEND_4(max, type) \ -{ \ - int64_t r, g, b, a; \ - int64_t pixel_opacity, pixel_transparency; \ - \ - pixel_opacity = opacity * input4 / max; \ - pixel_transparency = (max - pixel_opacity) * output[3] / max; \ - \ - switch(mode) \ - { \ - case TRANSFER_DIVIDE: \ - r = output[0] ? (((int64_t)input1 * max) / output[0]) : max; \ - g = output[1] ? (((int64_t)input2 * max) / output[1]) : max; \ - b = output[2] ? (((int64_t)input3 * max) / output[2]) : max; \ - r = (r * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (g * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (b * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_MULTIPLY: \ - r = ((int64_t)input1 * output[0]) / max; \ - g = ((int64_t)input2 * output[1]) / max; \ - b = ((int64_t)input3 * output[2]) / max; \ - r = (r * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (g * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (b * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_SUBTRACT: \ - r = (((int64_t)input1 - output[0]) * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (((int64_t)input2 - output[1]) * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (((int64_t)input3 - output[2]) * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_ADDITION: \ - r = (((int64_t)input1 + output[0]) * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (((int64_t)input2 + output[1]) * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (((int64_t)input3 + output[2]) * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_REPLACE: \ - r = input1; \ - g = input2; \ - b = input3; \ - a = input4; \ - break; \ - case TRANSFER_NORMAL: \ - r = ((int64_t)input1 * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = ((int64_t)input2 * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = ((int64_t)input3 * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - } \ - \ - output[0] = (type)CLIP(r, 0, max); \ - output[1] = (type)CLIP(g, 0, max); \ - output[2] = (type)CLIP(b, 0, max); \ - output[3] = (type)a; \ -} - - - - - - - - -// Bicubic algorithm using multiprocessors -// input -> scale nearest integer boundaries -> temp -> translation -> blend -> output - -// Nearest neighbor algorithm using multiprocessors for blending -// input -> scale + translate -> blend -> output - - -int OverlayFrame::overlay(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, // 0 - 1 - int mode, - int interpolation_type) -{ - float w_scale = (out_x2 - out_x1) / (in_x2 - in_x1); - float h_scale = (out_y2 - out_y1) / (in_y2 - in_y1); - -//printf("OverlayFrame::overlay 1 %d %f\n", mode, alpha); -// Limit values - if(in_x1 < 0) - { - out_x1 += -in_x1 * w_scale; - in_x1 = 0; - } - else - if(in_x1 >= input->get_w()) - { - out_x1 -= (in_x1 - input->get_w()) * w_scale; - in_x1 = input->get_w(); - } - - if(in_y1 < 0) - { - out_y1 += -in_y1 * h_scale; - in_y1 = 0; - } - else - if(in_y1 >= input->get_h()) - { - out_y1 -= (in_y1 - input->get_h()) * h_scale; - in_y1 = input->get_h(); - } - - if(in_x2 < 0) - { - out_x2 += -in_x2 * w_scale; - in_x2 = 0; - } - else - if(in_x2 >= input->get_w()) - { - out_x2 -= (in_x2 - input->get_w()) * w_scale; - in_x2 = input->get_w(); - } - - if(in_y2 < 0) - { - out_y2 += -in_y2 * h_scale; - in_y2 = 0; - } - else - if(in_y2 >= input->get_h()) - { - out_y2 -= (in_y2 - input->get_h()) * h_scale; - in_y2 = input->get_h(); - } - - if(out_x1 < 0) - { - in_x1 += -out_x1 / w_scale; - out_x1 = 0; - } - else - if(out_x1 >= output->get_w()) - { - in_x1 -= (out_x1 - output->get_w()) / w_scale; - out_x1 = output->get_w(); - } - - if(out_y1 < 0) - { - in_y1 += -out_y1 / h_scale; - out_y1 = 0; - } - else - if(out_y1 >= output->get_h()) - { - in_y1 -= (out_y1 - output->get_h()) / h_scale; - out_y1 = output->get_h(); - } - - if(out_x2 < 0) - { - in_x2 += -out_x2 / w_scale; - out_x2 = 0; - } - else - if(out_x2 >= output->get_w()) - { - in_x2 -= (out_x2 - output->get_w()) / w_scale; - out_x2 = output->get_w(); - } - - if(out_y2 < 0) - { - in_y2 += -out_y2 / h_scale; - out_y2 = 0; - } - else - if(out_y2 >= output->get_h()) - { - in_y2 -= (out_y2 - output->get_h()) / h_scale; - out_y2 = output->get_h(); - } - - - - - - float in_w = in_x2 - in_x1; - float in_h = in_y2 - in_y1; - float out_w = out_x2 - out_x1; - float out_h = out_y2 - out_y1; -// Input for translation operation - VFrame *translation_input = input; - - - -// printf("OverlayFrame::overlay %f %f %f %f -> %f %f %f %f\n", in_x1, -// in_y1, -// in_x2, -// in_y2, -// out_x1, -// out_y1, -// out_x2, -// out_y2); - - - - - -// **************************************************************************** -// Transfer to temp buffer by scaling nearest integer boundaries -// **************************************************************************** - if(interpolation_type != NEAREST_NEIGHBOR && - interpolation_type != LINEAR_LINEAR && - (!EQUIV(w_scale, 1) || !EQUIV(h_scale, 1))) - { -// Create integer boundaries for interpolation - int in_x1_int = (int)in_x1; - int in_y1_int = (int)in_y1; - int in_x2_int = MIN((int)ceil(in_x2), input->get_w()); - int in_y2_int = MIN((int)ceil(in_y2), input->get_h()); - -// Dimensions of temp frame. Integer boundaries scaled. - int temp_w = (int)ceil(w_scale * (in_x2_int - in_x1_int)); - int temp_h = (int)ceil(h_scale * (in_y2_int - in_y1_int)); - VFrame *scale_output; - - - -#define NO_TRANSLATION1 \ - (EQUIV(in_x1, 0) && \ - EQUIV(in_y1, 0) && \ - EQUIV(out_x1, 0) && \ - EQUIV(out_y1, 0) && \ - EQUIV(in_x2, in_x2_int) && \ - EQUIV(in_y2, in_y2_int) && \ - EQUIV(out_x2, temp_w) && \ - EQUIV(out_y2, temp_h)) - - -#define NO_BLEND \ - (EQUIV(alpha, 1) && \ - (mode == TRANSFER_REPLACE || \ - (mode == TRANSFER_NORMAL && cmodel_components(input->get_color_model()) == 3))) - - - - - -// Prepare destination for operation - -// No translation and no blending. The blending operation is built into the -// translation unit but not the scaling unit. -// input -> output - if(NO_TRANSLATION1 && - NO_BLEND) - { -// printf("OverlayFrame::overlay input -> output\n"); - - scale_output = output; - translation_input = 0; - } - else -// If translation or blending -// input -> nearest integer boundary temp - { - if(temp_frame && - (temp_frame->get_w() != temp_w || - temp_frame->get_h() != temp_h)) - { - delete temp_frame; - temp_frame = 0; - } - - if(!temp_frame) - { - temp_frame = new VFrame(0, - temp_w, - temp_h, - input->get_color_model(), - -1); - } -//printf("OverlayFrame::overlay input -> temp\n"); - - - temp_frame->clear_frame(); - -// printf("OverlayFrame::overlay 4 temp_w=%d temp_h=%d\n", -// temp_w, temp_h); - scale_output = temp_frame; - translation_input = scale_output; - -// Adjust input coordinates to reflect new scaled coordinates. - in_x1 = (in_x1 - in_x1_int) * w_scale; - in_y1 = (in_y1 - in_y1_int) * h_scale; - in_x2 = (in_x2 - in_x1_int) * w_scale; - in_y2 = (in_y2 - in_y1_int) * h_scale; - } - - - -//printf("Overlay 1\n"); - -// Scale input -> scale_output - if(!scale_engine) scale_engine = new ScaleEngine(this, cpus); - scale_engine->scale_output = scale_output; - scale_engine->scale_input = input; - scale_engine->w_scale = w_scale; - scale_engine->h_scale = h_scale; - scale_engine->in_x1_int = in_x1_int; - scale_engine->in_y1_int = in_y1_int; - scale_engine->out_w_int = temp_w; - scale_engine->out_h_int = temp_h; - scale_engine->interpolation_type = interpolation_type; -//printf("Overlay 2\n"); - -//printf("OverlayFrame::overlay ScaleEngine 1 %d\n", out_h_int); - scale_engine->process_packages(); -//printf("OverlayFrame::overlay ScaleEngine 2\n"); - - - - } - -// printf("OverlayFrame::overlay 1 %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", -// in_x1, -// in_y1, -// in_x2, -// in_y2, -// out_x1, -// out_y1, -// out_x2, -// out_y2); - - - - - -#define NO_TRANSLATION2 \ - (EQUIV(in_x1, 0) && \ - EQUIV(in_y1, 0) && \ - EQUIV(in_x2, translation_input->get_w()) && \ - EQUIV(in_y2, translation_input->get_h()) && \ - EQUIV(out_x1, 0) && \ - EQUIV(out_y1, 0) && \ - EQUIV(out_x2, output->get_w()) && \ - EQUIV(out_y2, output->get_h())) \ - -#define NO_SCALE \ - (EQUIV(out_x2 - out_x1, in_x2 - in_x1) && \ - EQUIV(out_y2 - out_y1, in_y2 - in_y1)) - - - - -//printf("OverlayFrame::overlay 4 %d\n", mode); - - - - - if(translation_input) - { -// Direct copy - if( NO_TRANSLATION2 && - NO_SCALE && - NO_BLEND) - { -//printf("OverlayFrame::overlay direct copy\n"); - output->copy_from(translation_input); - } - else -// Blend only - if( NO_TRANSLATION2 && - NO_SCALE) - { - if(!blend_engine) blend_engine = new BlendEngine(this, cpus); - - - blend_engine->output = output; - blend_engine->input = translation_input; - blend_engine->alpha = alpha; - blend_engine->mode = mode; - - blend_engine->process_packages(); - } - else -// Scale and translate using nearest neighbor -// Translation is exactly on integer boundaries - if(interpolation_type == NEAREST_NEIGHBOR || - EQUIV(in_x1, (int)in_x1) && - EQUIV(in_y1, (int)in_y1) && - EQUIV(in_x2, (int)in_x2) && - EQUIV(in_y2, (int)in_y2) && - - EQUIV(out_x1, (int)out_x1) && - EQUIV(out_y1, (int)out_y1) && - EQUIV(out_x2, (int)out_x2) && - EQUIV(out_y2, (int)out_y2)) - { -//printf("OverlayFrame::overlay NEAREST_NEIGHBOR 1\n"); - if(!scaletranslate_engine) scaletranslate_engine = new ScaleTranslateEngine(this, cpus); - - - scaletranslate_engine->output = output; - scaletranslate_engine->input = translation_input; - scaletranslate_engine->in_x1 = (int)in_x1; - scaletranslate_engine->in_y1 = (int)in_y1; - scaletranslate_engine->in_x2 = (int)in_x2; - scaletranslate_engine->in_y2 = (int)in_y2; - scaletranslate_engine->out_x1 = (int)out_x1; - scaletranslate_engine->out_y1 = (int)out_y1; - scaletranslate_engine->out_x2 = (int)out_x2; - scaletranslate_engine->out_y2 = (int)out_y2; - scaletranslate_engine->alpha = alpha; - scaletranslate_engine->mode = mode; - - scaletranslate_engine->process_packages(); - } - else -// Fractional translation - { -// Use fractional translation -// printf("OverlayFrame::overlay temp -> output %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", -// in_x1, -// in_y1, -// in_x2, -// in_y2, -// out_x1, -// out_y1, -// out_x2, -// out_y2); - -//printf("Overlay 3\n"); - if(!translate_engine) translate_engine = new TranslateEngine(this, cpus); - translate_engine->translate_output = output; - translate_engine->translate_input = translation_input; - translate_engine->translate_in_x1 = in_x1; - translate_engine->translate_in_y1 = in_y1; - translate_engine->translate_in_x2 = in_x2; - translate_engine->translate_in_y2 = in_y2; - translate_engine->translate_out_x1 = out_x1; - translate_engine->translate_out_y1 = out_y1; - translate_engine->translate_out_x2 = out_x2; - translate_engine->translate_out_y2 = out_y2; - translate_engine->translate_alpha = alpha; - translate_engine->translate_mode = mode; -//printf("Overlay 4\n"); - -//printf("OverlayFrame::overlay 5 %d\n", mode); - translate_engine->process_packages(); - - } - } -//printf("OverlayFrame::overlay 2\n"); - - return 0; -} - - - - - - - -ScalePackage::ScalePackage() -{ -} - - - - -ScaleUnit::ScaleUnit(ScaleEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; - this->engine = server; -} - -ScaleUnit::~ScaleUnit() -{ -} - - - -#define BILINEAR(max, type, components) \ -{ \ - float k_y = 1.0 / scale_h; \ - float k_x = 1.0 / scale_w; \ - type **in_rows = (type**)input->get_rows(); \ - type **out_rows = (type**)output->get_rows(); \ - type zero_r, zero_g, zero_b, zero_a; \ - int in_h_int = input->get_h(); \ - int in_w_int = input->get_w(); \ - int *table_int_x, *table_int_y; \ - float *table_frac_x, *table_antifrac_x, *table_frac_y, *table_antifrac_y; \ - \ - zero_r = 0; \ - zero_g = ((max + 1) >> 1) * (do_yuv); \ - zero_b = ((max + 1) >> 1) * (do_yuv); \ - if(components == 4) zero_a = 0; \ - \ - tabulate_blinear(table_int_x, table_frac_x, table_antifrac_x, k_x, 0, out_w_int, in_w_int); \ - tabulate_blinear(table_int_y, table_frac_y, table_antifrac_y, k_y, pkg->out_row1, pkg->out_row2, in_h_int); \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) \ - { \ - int i_y = table_int_y[i - pkg->out_row1]; \ - float a = table_frac_y[i - pkg->out_row1]; \ - float anti_a = table_antifrac_y[i - pkg->out_row1]; \ - type *in_row1 = in_rows[i_y + in_y1_int]; \ - type *in_row2 = (i_y + in_y1_int < in_h_int - 1) ? \ - in_rows[i_y + in_y1_int + 1] : \ - 0; \ - type *out_row = out_rows[i]; \ - \ - for(int j = 0; j < out_w_int; j++) \ - { \ - int i_x = table_int_x[j]; \ - float b = table_frac_x[j]; \ - float anti_b = table_antifrac_x[j]; \ - int x = i_x + in_x1_int; \ - float output1r, output1g, output1b, output1a; \ - float output2r, output2g, output2b, output2a; \ - float output3r, output3g, output3b, output3a; \ - float output4r, output4g, output4b, output4a; \ - \ - output1r = in_row1[x * components]; \ - output1g = in_row1[x * components + 1]; \ - output1b = in_row1[x * components + 2]; \ - if(components == 4) output1a = in_row1[x * components + 3]; \ - \ - if(x < in_w_int - 1) \ - { \ - output2r = in_row1[x * components + components]; \ - output2g = in_row1[x * components + components + 1]; \ - output2b = in_row1[x * components + components + 2]; \ - if(components == 4) output2a = in_row1[x * components + components + 3]; \ - \ - if(in_row2) \ - { \ - output4r = in_row2[x * components + components]; \ - output4g = in_row2[x * components + components + 1]; \ - output4b = in_row2[x * components + components + 2]; \ - if(components == 4) output4a = in_row2[x * components + components + 3]; \ - } \ - else \ - { \ - output4r = zero_r; \ - output4g = zero_g; \ - output4b = zero_b; \ - if(components == 4) output4a = zero_a; \ - } \ - } \ - else \ - { \ - output2r = zero_r; \ - output2g = zero_g; \ - output2b = zero_b; \ - if(components == 4) output2a = zero_a; \ - output4r = zero_r; \ - output4g = zero_g; \ - output4b = zero_b; \ - if(components == 4) output4a = zero_a; \ - } \ - \ - if(in_row2) \ - { \ - output3r = in_row2[x * components]; \ - output3g = in_row2[x * components + 1]; \ - output3b = in_row2[x * components + 2]; \ - if(components == 4) output3a = in_row2[x * components + 3]; \ - } \ - else \ - { \ - output3r = zero_r; \ - output3g = zero_g; \ - output3b = zero_b; \ - if(components == 4) output3a = zero_a; \ - } \ - \ - out_row[j * components] = \ - (type)((anti_a) * (((anti_b) * output1r) + \ - (b * output2r)) + \ - a * (((anti_b) * output3r) + \ - (b * output4r))); \ - out_row[j * components + 1] = \ - (type)((anti_a) * (((anti_b) * output1g) + \ - (b * output2g)) + \ - a * (((anti_b) * output3g) + \ - (b * output4g))); \ - out_row[j * components + 2] = \ - (type)((anti_a) * (((anti_b) * output1b) + \ - (b * output2b)) + \ - a * (((anti_b) * output3b) + \ - (b * output4b))); \ - if(components == 4) \ - out_row[j * components + 3] = \ - (type)((anti_a) * (((anti_b) * output1a) + \ - (b * output2a)) + \ - a * (((anti_b) * output3a) + \ - (b * output4a))); \ - } \ - } \ - \ - \ - delete [] table_int_x; \ - delete [] table_frac_x; \ - delete [] table_antifrac_x; \ - delete [] table_int_y; \ - delete [] table_frac_y; \ - delete [] table_antifrac_y; \ - \ -} - - -#define BICUBIC(max, type, components) \ -{ \ - float k_y = 1.0 / scale_h; \ - float k_x = 1.0 / scale_w; \ - type **in_rows = (type**)input->get_rows(); \ - type **out_rows = (type**)output->get_rows(); \ - float *bspline_x, *bspline_y; \ - int in_h_int = input->get_h(); \ - int in_w_int = input->get_w(); \ - type zero_r, zero_g, zero_b, zero_a; \ -/* printf("BICUBIC\n"); */ \ - \ - zero_r = 0; \ - zero_b = ((max + 1) >> 1) * (do_yuv); \ - zero_g = ((max + 1) >> 1) * (do_yuv); \ - if(components == 4) \ - zero_a = 0; \ - \ - tabulate_bspline(bspline_x, \ - k_x, \ - out_w_int, \ - -1); \ - \ - tabulate_bspline(bspline_y, \ - k_y, \ - out_h_int, \ - 1); \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) \ - { \ - int i_y = (int)(k_y * i); \ - \ - \ - for(int j = 0; j < out_w_int; j++) \ - { \ - int i_x = (int)(k_x * j); \ - float output1, output2, output3, output4; \ - output1 = 0; \ - output2 = 0; \ - output3 = 0; \ - if(components == 4) \ - output4 = 0; \ - int table_y = i * 4; \ - \ -/* Kernel */ \ - for(int m = -1; m < 3; m++) \ - { \ - float r1 = bspline_y[table_y++]; \ - int y = in_y1_int + i_y + m; \ - int table_x = j * 4; \ - \ - CLAMP(y, 0, in_h_int - 1); \ - \ - for(int n = -1; n < 3; n++) \ - { \ - float r2 = bspline_x[table_x++]; \ - int x = in_x1_int + i_x + n; \ - float r_square = r1 * r2; \ - \ - CLAMP(x, 0, in_w_int - 1); \ - \ - output1 += r_square * in_rows[y][x * components]; \ - output2 += r_square * in_rows[y][x * components + 1]; \ - output3 += r_square * in_rows[y][x * components + 2]; \ - if(components == 4) \ - output4 += r_square * in_rows[y][x * components + 3]; \ - } \ - } \ - \ - \ - out_rows[i][j * components] = (type)output1; \ - out_rows[i][j * components + 1] = (type)output2; \ - out_rows[i][j * components + 2] = (type)output3; \ - if(components == 4) \ - out_rows[i][j * components + 3] = (type)output4; \ - \ - } \ - } \ - \ - delete [] bspline_x; \ - delete [] bspline_y; \ -} - - - - -// Pow function is not thread safe in Compaqt C -#define CUBE(x) ((x) * (x) * (x)) - -float ScaleUnit::cubic_bspline(float x) -{ - float a, b, c, d; - - if((x + 2.0F) <= 0.0F) - { - a = 0.0F; - } - else - { - a = CUBE(x + 2.0F); - } - - - if((x + 1.0F) <= 0.0F) - { - b = 0.0F; - } - else - { - b = CUBE(x + 1.0F); - } - - if(x <= 0) - { - c = 0.0F; - } - else - { - c = CUBE(x); - } - - if((x - 1.0F) <= 0.0F) - { - d = 0.0F; - } - else - { - d = CUBE(x - 1.0F); - } - - - return (a - (4.0F * b) + (6.0F * c) - (4.0F * d)) / 6.0; -} - - -void ScaleUnit::tabulate_bspline(float* &table, - float scale, - int pixels, - float coefficient) -{ - table = new float[pixels * 4]; - for(int i = 0, j = 0; i < pixels; i++) - { - float f_x = (float)i * scale; - float a = f_x - floor(f_x); - - for(float m = -1; m < 3; m++) - { - table[j++] = cubic_bspline(coefficient * (m - a)); - } - - } -} - -void ScaleUnit::tabulate_blinear(int* &table_int, - float* &table_frac, - float* &table_antifrac, - float scale, - int pixel1, - int pixel2, - total_pixels) -{ - table_int = new int[pixel2 - pixel1]; - table_frac = new float[pixel2 - pixel1]; - table_antifrac = new float[pixel2 - pixel1]; - - for(int i = pixel1, j = 0; i < pixel2; i++, j++) - { - float f_x = (float)i * scale; - int i_x = (int)floor(f_x); - float a = (f_x - floor(f_x)); - - table_int[j] = CLAMP(i_x, 0, total_pixels - 1); - table_frac[j] = a; - table_antifrac[j] = 1.0F - a; - } -} - -void ScaleUnit::process_package(LoadPackage *package) -{ - ScalePackage *pkg = (ScalePackage*)package; - -//printf("ScaleUnit::process_package 1\n"); -// Arguments for macros - VFrame *output = engine->scale_output; - VFrame *input = engine->scale_input; - float scale_w = engine->w_scale; - float scale_h = engine->h_scale; - int in_x1_int = engine->in_x1_int; - int in_y1_int = engine->in_y1_int; - int out_h_int = engine->out_h_int; - int out_w_int = engine->out_w_int; - int do_yuv = - (input->get_color_model() == BC_YUV888 || - input->get_color_model() == BC_YUVA8888 || - input->get_color_model() == BC_YUV161616 || - input->get_color_model() == BC_YUVA16161616); - -//printf("ScaleUnit::process_package 2\n"); - if(engine->interpolation_type == CUBIC_CUBIC || - (engine->interpolation_type == CUBIC_LINEAR - && engine->w_scale > 1 && - engine->h_scale > 1)) - { - - switch(engine->scale_input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - BICUBIC(0xff, unsigned char, 3); - break; - - case BC_RGBA8888: - case BC_YUVA8888: - BICUBIC(0xff, unsigned char, 4); - break; - - case BC_RGB161616: - case BC_YUV161616: - BICUBIC(0xffff, uint16_t, 3); - break; - - case BC_RGBA16161616: - case BC_YUVA16161616: - BICUBIC(0xffff, uint16_t, 4); - break; - } - } - else -// Perform bilinear scaling input -> scale_output - { - switch(engine->scale_input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - BILINEAR(0xff, unsigned char, 3); - break; - - case BC_RGBA8888: - case BC_YUVA8888: - BILINEAR(0xff, unsigned char, 4); - break; - - case BC_RGB161616: - case BC_YUV161616: - BILINEAR(0xffff, uint16_t, 3); - break; - - case BC_RGBA16161616: - case BC_YUVA16161616: - BILINEAR(0xffff, uint16_t, 4); - break; - } - } -//printf("ScaleUnit::process_package 3\n"); - -} - - - - - - - - - - - - - -ScaleEngine::ScaleEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -ScaleEngine::~ScaleEngine() -{ -} - -void ScaleEngine::init_packages() -{ - for(int i = 0; i < total_packages; i++) - { - ScalePackage *package = (ScalePackage*)packages[i]; - package->out_row1 = out_h_int / total_packages * i; - package->out_row2 = package->out_row1 + out_h_int / total_packages; - - if(i >= total_packages - 1) - package->out_row2 = out_h_int; - } -} - -LoadClient* ScaleEngine::new_client() -{ - return new ScaleUnit(this, overlay); -} - -LoadPackage* ScaleEngine::new_package() -{ - return new ScalePackage; -} - - - - - - - - - - - - - -TranslatePackage::TranslatePackage() -{ -} - - - -TranslateUnit::TranslateUnit(TranslateEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; - this->engine = server; -} - -TranslateUnit::~TranslateUnit() -{ -} - - - -void TranslateUnit::translation_array(transfer_table* &table, - float out_x1, - float out_x2, - float in_x1, - float in_x2, - int in_total, - int out_total, - int &out_x1_int, - int &out_x2_int) -{ - int out_w_int; - float offset = out_x1 - in_x1; - - out_x1_int = (int)out_x1; - out_x2_int = MIN((int)ceil(out_x2), out_total); - out_w_int = out_x2_int - out_x1_int; - - table = new transfer_table[out_w_int]; - bzero(table, sizeof(transfer_table) * out_w_int); - - -//printf("OverlayFrame::translation_array 1 %f %f -> %f %f\n", in_x1, in_x2, out_x1, out_x2); - - float in_x = in_x1; - for(int out_x = out_x1_int; out_x < out_x2_int; out_x++) - { - transfer_table *entry = &table[out_x - out_x1_int]; - - entry->in_x1 = (int)in_x; - entry->in_x2 = (int)in_x + 1; - -// Get fraction of output pixel to fill - entry->output_fraction = 1; - - if(out_x1 > out_x) - { - entry->output_fraction -= out_x1 - out_x; - } - - if(out_x2 < out_x + 1) - { - entry->output_fraction = (out_x2 - out_x); - } - -// Advance in_x until out_x_fraction is filled - float out_x_fraction = entry->output_fraction; - float in_x_fraction = floor(in_x + 1) - in_x; - - if(out_x_fraction <= in_x_fraction) - { - entry->in_fraction1 = out_x_fraction; - entry->in_fraction2 = 0.0; - in_x += out_x_fraction; - } - else - { - entry->in_fraction1 = in_x_fraction; - in_x += out_x_fraction; - entry->in_fraction2 = in_x - floor(in_x); - } - -// Clip in_x and zero out fraction. This doesn't work for YUV. - if(entry->in_x2 >= in_total) - { - entry->in_x2 = in_total - 1; - entry->in_fraction2 = 0.0; - } - - if(entry->in_x1 >= in_total) - { - entry->in_x1 = in_total - 1; - entry->in_fraction1 = 0.0; - } -// printf("OverlayFrame::translation_array 2 %d %d %d %f %f %f\n", -// out_x, -// entry->in_x1, -// entry->in_x2, -// entry->in_fraction1, -// entry->in_fraction2, -// entry->output_fraction); - } -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define TRANSLATE(max, type, components) \ -{ \ - \ - type **in_rows = (type**)input->get_rows(); \ - type **out_rows = (type**)output->get_rows(); \ - \ -/* printf("OverlayFrame::translate 1 %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", */ \ -/* (in_x1), in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2); */ \ - \ - unsigned int master_opacity = (int)(alpha * max + 0.5); \ - unsigned int master_transparency = max - master_opacity; \ - type zero_r, zero_g, zero_b, zero_a; \ - zero_r = 0; \ - zero_b = ((max + 1) >> 1) * (do_yuv); \ - zero_g = ((max + 1) >> 1) * (do_yuv); \ - if(components == 4) \ - zero_a = 0; \ - \ -/* printf("TRANSLATE %d\n", mode); */ \ - \ - for(int i = row1; i < row2; i++) \ - { \ - int in_y1 = y_table[i - out_y1_int].in_x1; \ - int in_y2 = y_table[i - out_y1_int].in_x2; \ - float y_fraction1 = y_table[i - out_y1_int].in_fraction1; \ - float y_fraction2 = y_table[i - out_y1_int].in_fraction2; \ - float y_output_fraction = y_table[i - out_y1_int].output_fraction; \ - type *in_row1 = in_rows[(in_y1)]; \ - type *in_row2 = in_rows[(in_y2)]; \ - type *out_row = out_rows[i]; \ - \ - for(int j = out_x1_int; j < out_x2_int; j++) \ - { \ - int in_x1 = x_table[j - out_x1_int].in_x1; \ - int in_x2 = x_table[j - out_x1_int].in_x2; \ - float x_fraction1 = x_table[j - out_x1_int].in_fraction1; \ - float x_fraction2 = x_table[j - out_x1_int].in_fraction2; \ - float x_output_fraction = x_table[j - out_x1_int].output_fraction; \ - type *output = &out_row[j * components]; \ - int input1, input2, input3, input4; \ - \ - input1 = (int)(in_row1[in_x1 * components] * x_fraction1 * y_fraction1 + \ - in_row1[in_x2 * components] * x_fraction2 * y_fraction1 + \ - in_row2[in_x1 * components] * x_fraction1 * y_fraction2 + \ - in_row2[in_x2 * components] * x_fraction2 * y_fraction2 + 0.5); \ - input2 = (int)(in_row1[in_x1 * components + 1] * x_fraction1 * y_fraction1 + \ - in_row1[in_x2 * components + 1] * x_fraction2 * y_fraction1 + \ - in_row2[in_x1 * components + 1] * x_fraction1 * y_fraction2 + \ - in_row2[in_x2 * components + 1] * x_fraction2 * y_fraction2 + 0.5); \ - input3 = (int)(in_row1[in_x1 * components + 2] * x_fraction1 * y_fraction1 + \ - in_row1[in_x2 * components + 2] * x_fraction2 * y_fraction1 + \ - in_row2[in_x1 * components + 2] * x_fraction1 * y_fraction2 + \ - in_row2[in_x2 * components + 2] * x_fraction2 * y_fraction2 + 0.5); \ - if(components == 4) \ - input4 = (int)(in_row1[in_x1 * components + 3] * x_fraction1 * y_fraction1 + \ - in_row1[in_x2 * components + 3] * x_fraction2 * y_fraction1 + \ - in_row2[in_x1 * components + 3] * x_fraction1 * y_fraction2 + \ - in_row2[in_x2 * components + 3] * x_fraction2 * y_fraction2 + 0.5); \ - \ - unsigned int opacity = (int)(master_opacity * \ - y_output_fraction * \ - x_output_fraction + 0.5); \ - unsigned int transparency = max - opacity; \ - \ -/* if(opacity != max) printf("TRANSLATE %x %d %d\n", opacity, j, i); */ \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - } \ - } \ -} - -void TranslateUnit::process_package(LoadPackage *package) -{ - TranslatePackage *pkg = (TranslatePackage*)package; - int out_y1_int; - int out_y2_int; - int out_x1_int; - int out_x2_int; - - -// Variables for TRANSLATE - VFrame *input = engine->translate_input; - VFrame *output = engine->translate_output; - float in_x1 = engine->translate_in_x1; - float in_y1 = engine->translate_in_y1; - float in_x2 = engine->translate_in_x2; - float in_y2 = engine->translate_in_y2; - float out_x1 = engine->translate_out_x1; - float out_y1 = engine->translate_out_y1; - float out_x2 = engine->translate_out_x2; - float out_y2 = engine->translate_out_y2; - float alpha = engine->translate_alpha; - int row1 = pkg->out_row1; - int row2 = pkg->out_row2; - int mode = engine->translate_mode; - int in_total_x = input->get_w(); - int in_total_y = input->get_h(); - int do_yuv = - (engine->translate_input->get_color_model() == BC_YUV888 || - engine->translate_input->get_color_model() == BC_YUVA8888 || - engine->translate_input->get_color_model() == BC_YUV161616 || - engine->translate_input->get_color_model() == BC_YUVA16161616); - - transfer_table *x_table; - transfer_table *y_table; - - translation_array(x_table, - out_x1, - out_x2, - in_x1, - in_x2, - in_total_x, - output->get_w(), - out_x1_int, - out_x2_int); - translation_array(y_table, - out_y1, - out_y2, - in_y1, - in_y2, - in_total_y, - output->get_h(), - out_y1_int, - out_y2_int); - - switch(engine->translate_input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - TRANSLATE(0xff, unsigned char, 3); - break; - - case BC_RGBA8888: - case BC_YUVA8888: - TRANSLATE(0xff, unsigned char, 4); - break; - - case BC_RGB161616: - case BC_YUV161616: - TRANSLATE(0xffff, uint16_t, 3); - break; - - case BC_RGBA16161616: - case BC_YUVA16161616: - TRANSLATE(0xffff, uint16_t, 4); - break; - } - - delete [] x_table; - delete [] y_table; -} - - - - - - - - - - -TranslateEngine::TranslateEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -TranslateEngine::~TranslateEngine() -{ -} - -void TranslateEngine::init_packages() -{ - int out_y1_int = (int)translate_out_y1; - int out_y2_int = MIN((int)ceil(translate_out_y2), translate_output->get_h()); - int out_h = out_y2_int - out_y1_int; - - for(int i = 0; i < total_packages; i++) - { - TranslatePackage *package = (TranslatePackage*)packages[i]; - package->out_row1 = (int)(out_y1_int + out_h / - total_packages * - i); - package->out_row2 = (int)((float)package->out_row1 + - out_h / - total_packages); - if(i >= total_packages - 1) - package->out_row2 = out_y2_int; - } -} - -LoadClient* TranslateEngine::new_client() -{ - return new TranslateUnit(this, overlay); -} - -LoadPackage* TranslateEngine::new_package() -{ - return new TranslatePackage; -} - - - - - - - - -#define SCALE_TRANSLATE(max, type, components) \ -{ \ - int64_t opacity = (int)(alpha * max + 0.5); \ - int64_t transparency = max - opacity; \ - int out_w = out_x2 - out_x1; \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) \ - { \ - int in_y = y_table[i - out_y1]; \ - type *in_row = (type*)in_rows[in_y] + in_x1 * components; \ - type *out_row = (type*)out_rows[i] + out_x1 * components; \ - \ -/* X direction is scaled and requires a table lookup */ \ - if(out_w != in_x2 - in_x1) \ - { \ - for(int j = 0; j < out_w; j++) \ - { \ - int in_x = x_table[j]; \ - int input1, input2, input3, input4; \ - type *output = out_row + j * components; \ - \ - input1 = in_row[in_x * components]; \ - input2 = in_row[in_x * components + 1]; \ - input3 = in_row[in_x * components + 2]; \ - if(components == 4) \ - input4 = in_row[in_x * components + 3]; \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - } \ - } \ - else \ -/* X direction is not scaled */ \ - { \ - for(int j = 0; j < out_w; j++) \ - { \ - int input1, input2, input3, input4; \ - type *output = out_row + j * components; \ - \ - input1 = in_row[j * components]; \ - input2 = in_row[j * components + 1]; \ - input3 = in_row[j * components + 2]; \ - if(components == 4) \ - input4 = in_row[j * components + 3]; \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - } \ - } \ - } \ -} - - - -ScaleTranslateUnit::ScaleTranslateUnit(ScaleTranslateEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; - this->scale_translate = server; -} - -ScaleTranslateUnit::~ScaleTranslateUnit() -{ -} - -void ScaleTranslateUnit::scale_array(int* &table, - int out_x1, - int out_x2, - int in_x1, - int in_x2, - int is_x) -{ - float scale = (float)(out_x2 - out_x1) / (in_x2 - in_x1); - - table = new int[out_x2 - out_x1]; - - if(!is_x) - { - for(int i = 0; i < out_x2 - out_x1; i++) - { - table[i] = (int)((float)i / scale + in_x1); - } - } - else - { - for(int i = 0; i < out_x2 - out_x1; i++) - { - table[i] = (int)((float)i / scale); - } - } -} - - -void ScaleTranslateUnit::process_package(LoadPackage *package) -{ - ScaleTranslatePackage *pkg = (ScaleTranslatePackage*)package; - -// Args for NEAREST_NEIGHBOR_MACRO - VFrame *output = scale_translate->output; - VFrame *input = scale_translate->input; - int in_x1 = scale_translate->in_x1; - int in_y1 = scale_translate->in_y1; - int in_x2 = scale_translate->in_x2; - int in_y2 = scale_translate->in_y2; - int out_x1 = scale_translate->out_x1; - int out_y1 = scale_translate->out_y1; - int out_x2 = scale_translate->out_x2; - int out_y2 = scale_translate->out_y2; - float alpha = scale_translate->alpha; - int mode = scale_translate->mode; - - int *x_table; - int *y_table; - unsigned char **in_rows = input->get_rows(); - unsigned char **out_rows = output->get_rows(); - - scale_array(x_table, - out_x1, - out_x2, - in_x1, - in_x2, - 1); - scale_array(y_table, - out_y1, - out_y2, - in_y1, - in_y2, - 0); - - - switch(input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - SCALE_TRANSLATE(0xff, uint8_t, 3); - break; - - case BC_RGBA8888: - case BC_YUVA8888: - SCALE_TRANSLATE(0xff, uint8_t, 4); - break; - - - case BC_RGB161616: - case BC_YUV161616: - SCALE_TRANSLATE(0xffff, uint16_t, 3); - break; - - case BC_RGBA16161616: - case BC_YUVA16161616: - SCALE_TRANSLATE(0xffff, uint16_t, 4); - break; - } - - delete [] x_table; - delete [] y_table; - -}; - - - - - - - - - -ScaleTranslateEngine::ScaleTranslateEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -ScaleTranslateEngine::~ScaleTranslateEngine() -{ -} - -void ScaleTranslateEngine::init_packages() -{ - int out_h = out_y2 - out_y1; - - for(int i = 0; i < total_packages; i++) - { - ScaleTranslatePackage *package = (ScaleTranslatePackage*)packages[i]; - package->out_row1 = (int)(out_y1 + out_h / - total_packages * - i); - package->out_row2 = (int)((float)package->out_row1 + - out_h / - total_packages); - if(i >= total_packages - 1) - package->out_row2 = out_y2; - } -} - -LoadClient* ScaleTranslateEngine::new_client() -{ - return new ScaleTranslateUnit(this, overlay); -} - -LoadPackage* ScaleTranslateEngine::new_package() -{ - return new ScaleTranslatePackage; -} - - -ScaleTranslatePackage::ScaleTranslatePackage() -{ -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define BLEND_ONLY(type, max, components) \ -{ \ - int64_t opacity = (int)(alpha * max + 0.5); \ - int64_t transparency = max - opacity; \ - \ - type** output_rows = (type**)output->get_rows(); \ - type** input_rows = (type**)input->get_rows(); \ - int w = input->get_w(); \ - int h = input->get_h(); \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) \ - { \ - type* in_row = input_rows[i]; \ - type* output = output_rows[i]; \ - \ - for(int j = 0; j < w; j++) \ - { \ - int input1, input2, input3, input4; \ - input1 = in_row[j * components]; \ - input2 = in_row[j * components + 1]; \ - input3 = in_row[j * components + 2]; \ - if(components == 4) input4 = in_row[j * components + 3]; \ - \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - \ - input += components; \ - output += components; \ - } \ - } \ -} - - - - -BlendUnit::BlendUnit(BlendEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; - this->blend_engine = server; -} - -BlendUnit::~BlendUnit() -{ -} - -void BlendUnit::process_package(LoadPackage *package) -{ - BlendPackage *pkg = (BlendPackage*)package; - - - VFrame *output = blend_engine->output; - VFrame *input = blend_engine->input; - float alpha = blend_engine->alpha; - int mode = blend_engine->mode; - - switch(input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - BLEND_ONLY(unsigned char, 0xff, 3); - break; - case BC_RGBA8888: - case BC_YUVA8888: - BLEND_ONLY(unsigned char, 0xff, 4); - break; - case BC_RGB161616: - case BC_YUV161616: - BLEND_ONLY(uint16_t, 0xffff, 3); - break; - case BC_RGBA16161616: - case BC_YUVA16161616: - BLEND_ONLY(uint16_t, 0xffff, 4); - break; - } -} - - - -BlendEngine::BlendEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -BlendEngine::~BlendEngine() -{ -} - -void BlendEngine::init_packages() -{ - for(int i = 0; i < total_packages; i++) - { - BlendPackage *package = (BlendPackage*)packages[i]; - package->out_row1 = (int)(input->get_h() / - total_packages * - i); - package->out_row2 = (int)((float)package->out_row1 + - input->get_h() / - total_packages); - - if(i >= total_packages - 1) - package->out_row2 = input->get_h(); - } -} - -LoadClient* BlendEngine::new_client() -{ - return new BlendUnit(this, overlay); -} - -LoadPackage* BlendEngine::new_package() -{ - return new BlendPackage; -} - - -BlendPackage::BlendPackage() -{ -} - - diff --git a/cinelerra-5.1/cinelerra/overlayframe.C.int b/cinelerra-5.1/cinelerra/overlayframe.C.int deleted file mode 100644 index f241c1fb..00000000 --- a/cinelerra-5.1/cinelerra/overlayframe.C.int +++ /dev/null @@ -1,1749 +0,0 @@ -#include -#include -#include -#include - -#include "clip.h" -#include "edl.inc" -#include "mutex.h" -#include "overlayframe.h" -#include "vframe.h" - -OverlayFrame::OverlayFrame(int cpus) -{ - temp_frame = 0; - blend_engine = 0; - scale_engine = 0; - scaletranslate_engine = 0; - translate_engine = 0; - this->cpus = cpus; -} - -OverlayFrame::~OverlayFrame() -{ -//printf("OverlayFrame::~OverlayFrame 1\n"); - if(temp_frame) delete temp_frame; - if(scale_engine) delete scale_engine; - if(translate_engine) delete translate_engine; - if(blend_engine) delete blend_engine; - if(scaletranslate_engine) delete scaletranslate_engine; -//printf("OverlayFrame::~OverlayFrame 2\n"); -} - - - - - - - - -// Verification: - -// (255 * 255 + 0 * 0) / 255 = 255 -// (255 * 127 + 255 * (255 - 127)) / 255 = 255 - -// (65535 * 65535 + 0 * 0) / 65535 = 65535 -// (65535 * 32767 + 65535 * (65535 - 32767)) / 65535 = 65535 - - -// Branch prediction 4 U - -#define BLEND_3(max, type) \ -{ \ - int64_t r, g, b; \ - \ -/* if(mode != TRANSFER_NORMAL) printf("BLEND mode = %d\n", mode); */ \ - switch(mode) \ - { \ - case TRANSFER_DIVIDE: \ - r = output[0] ? (((int64_t)input1 * max) / output[0]) : max; \ - g = output[1] ? (((int64_t)input2 * max) / output[1]) : max; \ - b = output[2] ? (((int64_t)input3 * max) / output[2]) : max; \ - r = (r * opacity + output[0] * transparency) / max; \ - g = (g * opacity + output[1] * transparency) / max; \ - b = (b * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_MULTIPLY: \ - r = ((int64_t)input1 * output[0]) / max; \ - g = ((int64_t)input2 * output[1]) / max; \ - b = ((int64_t)input3 * output[2]) / max; \ - r = (r * opacity + output[0] * transparency) / max; \ - g = (g * opacity + output[1] * transparency) / max; \ - b = (b * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_SUBTRACT: \ - r = (((int64_t)input1 - output[0]) * opacity + output[0] * transparency) / max; \ - g = (((int64_t)input2 - output[1]) * opacity + output[1] * transparency) / max; \ - b = (((int64_t)input3 - output[2]) * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_ADDITION: \ - r = (((int64_t)input1 + output[0]) * opacity + output[0] * transparency) / max; \ - g = (((int64_t)input2 + output[1]) * opacity + output[1] * transparency) / max; \ - b = (((int64_t)input3 + output[2]) * opacity + output[2] * transparency) / max; \ - break; \ - case TRANSFER_REPLACE: \ - r = input1; \ - g = input2; \ - b = input3; \ - break; \ - case TRANSFER_NORMAL: \ - r = ((int64_t)input1 * opacity + output[0] * transparency) / max; \ - g = ((int64_t)input2 * opacity + output[1] * transparency) / max; \ - b = ((int64_t)input3 * opacity + output[2] * transparency) / max; \ - break; \ - } \ - \ - output[0] = (type)CLIP(r, 0, max); \ - output[1] = (type)CLIP(g, 0, max); \ - output[2] = (type)CLIP(b, 0, max); \ -} - - - - - -// Blending equations are drastically different for 3 and 4 components -#define BLEND_4(max, type) \ -{ \ - int64_t r, g, b, a; \ - int64_t pixel_opacity, pixel_transparency; \ - \ - pixel_opacity = opacity * input4 / max; \ - pixel_transparency = (max - pixel_opacity) * output[3] / max; \ - \ - switch(mode) \ - { \ - case TRANSFER_DIVIDE: \ - r = output[0] ? (((int64_t)input1 * max) / output[0]) : max; \ - g = output[1] ? (((int64_t)input2 * max) / output[1]) : max; \ - b = output[2] ? (((int64_t)input3 * max) / output[2]) : max; \ - r = (r * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (g * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (b * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_MULTIPLY: \ - r = ((int64_t)input1 * output[0]) / max; \ - g = ((int64_t)input2 * output[1]) / max; \ - b = ((int64_t)input3 * output[2]) / max; \ - r = (r * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (g * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (b * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_SUBTRACT: \ - r = (((int64_t)input1 - output[0]) * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (((int64_t)input2 - output[1]) * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (((int64_t)input3 - output[2]) * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_ADDITION: \ - r = (((int64_t)input1 + output[0]) * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = (((int64_t)input2 + output[1]) * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = (((int64_t)input3 + output[2]) * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - case TRANSFER_REPLACE: \ - r = input1; \ - g = input2; \ - b = input3; \ - a = input4; \ - break; \ - case TRANSFER_NORMAL: \ - r = ((int64_t)input1 * pixel_opacity + output[0] * pixel_transparency) / max; \ - g = ((int64_t)input2 * pixel_opacity + output[1] * pixel_transparency) / max; \ - b = ((int64_t)input3 * pixel_opacity + output[2] * pixel_transparency) / max; \ - a = input4 > output[3] ? input4 : output[3]; \ - break; \ - } \ - \ - output[0] = (type)CLIP(r, 0, max); \ - output[1] = (type)CLIP(g, 0, max); \ - output[2] = (type)CLIP(b, 0, max); \ - output[3] = (type)a; \ -} - - - - - - - - -// Bicubic algorithm using multiprocessors -// input -> scale nearest integer boundaries -> temp -> translation -> blend -> output - -// Nearest neighbor algorithm using multiprocessors for blending -// input -> scale + translate -> blend -> output - - -int OverlayFrame::overlay(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, // 0 - 1 - int mode, - int interpolation_type) -{ - float w_scale = (out_x2 - out_x1) / (in_x2 - in_x1); - float h_scale = (out_y2 - out_y1) / (in_y2 - in_y1); - -//printf("OverlayFrame::overlay 1 %d %f\n", mode, alpha); -// Limit values - if(in_x1 < 0) - { - out_x1 += -in_x1 * w_scale; - in_x1 = 0; - } - else - if(in_x1 >= input->get_w()) - { - out_x1 -= (in_x1 - input->get_w()) * w_scale; - in_x1 = input->get_w(); - } - - if(in_y1 < 0) - { - out_y1 += -in_y1 * h_scale; - in_y1 = 0; - } - else - if(in_y1 >= input->get_h()) - { - out_y1 -= (in_y1 - input->get_h()) * h_scale; - in_y1 = input->get_h(); - } - - if(in_x2 < 0) - { - out_x2 += -in_x2 * w_scale; - in_x2 = 0; - } - else - if(in_x2 >= input->get_w()) - { - out_x2 -= (in_x2 - input->get_w()) * w_scale; - in_x2 = input->get_w(); - } - - if(in_y2 < 0) - { - out_y2 += -in_y2 * h_scale; - in_y2 = 0; - } - else - if(in_y2 >= input->get_h()) - { - out_y2 -= (in_y2 - input->get_h()) * h_scale; - in_y2 = input->get_h(); - } - - if(out_x1 < 0) - { - in_x1 += -out_x1 / w_scale; - out_x1 = 0; - } - else - if(out_x1 >= output->get_w()) - { - in_x1 -= (out_x1 - output->get_w()) / w_scale; - out_x1 = output->get_w(); - } - - if(out_y1 < 0) - { - in_y1 += -out_y1 / h_scale; - out_y1 = 0; - } - else - if(out_y1 >= output->get_h()) - { - in_y1 -= (out_y1 - output->get_h()) / h_scale; - out_y1 = output->get_h(); - } - - if(out_x2 < 0) - { - in_x2 += -out_x2 / w_scale; - out_x2 = 0; - } - else - if(out_x2 >= output->get_w()) - { - in_x2 -= (out_x2 - output->get_w()) / w_scale; - out_x2 = output->get_w(); - } - - if(out_y2 < 0) - { - in_y2 += -out_y2 / h_scale; - out_y2 = 0; - } - else - if(out_y2 >= output->get_h()) - { - in_y2 -= (out_y2 - output->get_h()) / h_scale; - out_y2 = output->get_h(); - } - - - - - - float in_w = in_x2 - in_x1; - float in_h = in_y2 - in_y1; - float out_w = out_x2 - out_x1; - float out_h = out_y2 - out_y1; -// Input for translation operation - VFrame *translation_input = input; - - - -// printf("OverlayFrame::overlay %f %f %f %f -> %f %f %f %f\n", in_x1, -// in_y1, -// in_x2, -// in_y2, -// out_x1, -// out_y1, -// out_x2, -// out_y2); - - - - - -// **************************************************************************** -// Transfer to temp buffer by scaling nearest integer boundaries -// **************************************************************************** - if(interpolation_type != NEAREST_NEIGHBOR && - (!EQUIV(w_scale, 1) || !EQUIV(h_scale, 1))) - { -// Create integer boundaries for interpolation - int in_x1_int = (int)in_x1; - int in_y1_int = (int)in_y1; - int in_x2_int = MIN((int)ceil(in_x2), input->get_w()); - int in_y2_int = MIN((int)ceil(in_y2), input->get_h()); - -// Dimensions of temp frame. Integer boundaries scaled. - int temp_w = (int)ceil(w_scale * (in_x2_int - in_x1_int)); - int temp_h = (int)ceil(h_scale * (in_y2_int - in_y1_int)); - VFrame *scale_output; - - - -#define NO_TRANSLATION1 \ - (EQUIV(in_x1, 0) && \ - EQUIV(in_y1, 0) && \ - EQUIV(out_x1, 0) && \ - EQUIV(out_y1, 0) && \ - EQUIV(in_x2, in_x2_int) && \ - EQUIV(in_y2, in_y2_int) && \ - EQUIV(out_x2, temp_w) && \ - EQUIV(out_y2, temp_h)) - - -#define NO_BLEND \ - (EQUIV(alpha, 1) && \ - (mode == TRANSFER_REPLACE || \ - (mode == TRANSFER_NORMAL && cmodel_components(input->get_color_model()) == 3))) - - - - - -// Prepare destination for operation - -// No translation and no blending. The blending operation is built into the -// translation unit but not the scaling unit. -// input -> output - if(NO_TRANSLATION1 && - NO_BLEND) - { -// printf("OverlayFrame::overlay input -> output\n"); - - scale_output = output; - translation_input = 0; - } - else -// If translation or blending -// input -> nearest integer boundary temp - { - if(temp_frame && - (temp_frame->get_w() != temp_w || - temp_frame->get_h() != temp_h)) - { - delete temp_frame; - temp_frame = 0; - } - - if(!temp_frame) - { - temp_frame = new VFrame(0, - temp_w, - temp_h, - input->get_color_model(), - -1); - } -//printf("OverlayFrame::overlay input -> temp\n"); - - - temp_frame->clear_frame(); - -// printf("OverlayFrame::overlay 4 temp_w=%d temp_h=%d\n", -// temp_w, temp_h); - scale_output = temp_frame; - translation_input = scale_output; - -// Adjust input coordinates to reflect new scaled coordinates. - in_x1 = (in_x1 - in_x1_int) * w_scale; - in_y1 = (in_y1 - in_y1_int) * h_scale; - in_x2 = (in_x2 - in_x1_int) * w_scale; - in_y2 = (in_y2 - in_y1_int) * h_scale; - } - - - - -// Scale input -> scale_output - this->scale_output = scale_output; - this->scale_input = input; - this->w_scale = w_scale; - this->h_scale = h_scale; - this->in_x1_int = in_x1_int; - this->in_y1_int = in_y1_int; - this->out_w_int = temp_w; - this->out_h_int = temp_h; - this->interpolation_type = interpolation_type; - -//printf("OverlayFrame::overlay ScaleEngine 1 %d\n", out_h_int); - if(!scale_engine) scale_engine = new ScaleEngine(this, cpus); - scale_engine->process_packages(); -//printf("OverlayFrame::overlay ScaleEngine 2\n"); - - - - } - -// printf("OverlayFrame::overlay 1 %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", -// in_x1, -// in_y1, -// in_x2, -// in_y2, -// out_x1, -// out_y1, -// out_x2, -// out_y2); - - - - - -#define NO_TRANSLATION2 \ - (EQUIV(in_x1, 0) && \ - EQUIV(in_y1, 0) && \ - EQUIV(in_x2, translation_input->get_w()) && \ - EQUIV(in_y2, translation_input->get_h()) && \ - EQUIV(out_x1, 0) && \ - EQUIV(out_y1, 0) && \ - EQUIV(out_x2, output->get_w()) && \ - EQUIV(out_y2, output->get_h())) \ - -#define NO_SCALE \ - (EQUIV(out_x2 - out_x1, in_x2 - in_x1) && \ - EQUIV(out_y2 - out_y1, in_y2 - in_y1)) - - - - -//printf("OverlayFrame::overlay 4 %d\n", mode); - - - - - if(translation_input) - { -// Direct copy - if( NO_TRANSLATION2 && - NO_SCALE && - NO_BLEND) - { -//printf("OverlayFrame::overlay direct copy\n"); - output->copy_from(translation_input); - } - else -// Blend only - if( NO_TRANSLATION2 && - NO_SCALE) - { - if(!blend_engine) blend_engine = new BlendEngine(this, cpus); - - - blend_engine->output = output; - blend_engine->input = translation_input; - blend_engine->alpha = alpha; - blend_engine->mode = mode; - - blend_engine->process_packages(); - } - else -// Scale and translate using nearest neighbor -// Translation is exactly on integer boundaries - if(interpolation_type == NEAREST_NEIGHBOR || - EQUIV(in_x1, (int)in_x1) && - EQUIV(in_y1, (int)in_y1) && - EQUIV(in_x2, (int)in_x2) && - EQUIV(in_y2, (int)in_y2) && - - EQUIV(out_x1, (int)out_x1) && - EQUIV(out_y1, (int)out_y1) && - EQUIV(out_x2, (int)out_x2) && - EQUIV(out_y2, (int)out_y2)) - { -//printf("OverlayFrame::overlay NEAREST_NEIGHBOR 1\n"); - if(!scaletranslate_engine) scaletranslate_engine = new ScaleTranslateEngine(this, cpus); - - - scaletranslate_engine->output = output; - scaletranslate_engine->input = translation_input; - scaletranslate_engine->in_x1 = (int)in_x1; - scaletranslate_engine->in_y1 = (int)in_y1; - scaletranslate_engine->in_x2 = (int)in_x2; - scaletranslate_engine->in_y2 = (int)in_y2; - scaletranslate_engine->out_x1 = (int)out_x1; - scaletranslate_engine->out_y1 = (int)out_y1; - scaletranslate_engine->out_x2 = (int)out_x2; - scaletranslate_engine->out_y2 = (int)out_y2; - scaletranslate_engine->alpha = alpha; - scaletranslate_engine->mode = mode; - - scaletranslate_engine->process_packages(); - } - else -// Fractional translation - { -// Use fractional translation -// printf("OverlayFrame::overlay temp -> output %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", -// in_x1, -// in_y1, -// in_x2, -// in_y2, -// out_x1, -// out_y1, -// out_x2, -// out_y2); - this->translate_output = output; - this->translate_input = translation_input; - this->translate_in_x1 = in_x1; - this->translate_in_y1 = in_y1; - this->translate_in_x2 = in_x2; - this->translate_in_y2 = in_y2; - this->translate_out_x1 = out_x1; - this->translate_out_y1 = out_y1; - this->translate_out_x2 = out_x2; - this->translate_out_y2 = out_y2; - this->translate_alpha = alpha; - this->translate_mode = mode; - -//printf("OverlayFrame::overlay 5 %d\n", mode); - if(!translate_engine) translate_engine = new TranslateEngine(this, cpus); - translate_engine->process_packages(); - - } - } -//printf("OverlayFrame::overlay 2\n"); - - return 0; -} - - - - - - - -ScalePackage::ScalePackage() -{ -} - - - - -ScaleUnit::ScaleUnit(ScaleEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; -} - -ScaleUnit::~ScaleUnit() -{ -} - - - -#define BILINEAR(max, type, components) \ -{ \ - float k_y = 1.0 / scale_h; \ - float k_x = 1.0 / scale_w; \ - type **in_rows = (type**)input->get_rows(); \ - type **out_rows = (type**)output->get_rows(); \ - type zero_r, zero_g, zero_b, zero_a; \ - int in_h_int = input->get_h(); \ - int in_w_int = input->get_w(); \ - int *table_int_x, *table_int_y; \ - int *table_frac_x, *table_frac_y; \ - \ - zero_r = 0; \ - zero_g = ((max + 1) >> 1) * (do_yuv); \ - zero_b = ((max + 1) >> 1) * (do_yuv); \ - if(components == 4) zero_a = 0; \ - \ - tabulate_blinear(table_int_x, table_frac_x, k_x, 0, out_w_int); \ - tabulate_blinear(table_int_y, table_frac_y, k_y, pkg->out_row1, pkg->out_row2); \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) \ - { \ - int i_y = table_int_y[i - pkg->out_row1]; \ - uint64_t a = table_frac_y[i - pkg->out_row1]; \ - uint64_t anti_a = 0xffff - a; \ - type *in_row1 = in_rows[i_y + in_y1_int]; \ - type *in_row2 = (i_y + in_y1_int < in_h_int - 1) ? \ - in_rows[i_y + in_y1_int + 1] : \ - 0; \ - type *out_row = out_rows[i]; \ - \ - for(int j = 0; j < out_w_int; j++) \ - { \ - int i_x = table_int_x[j]; \ - uint64_t b = table_frac_x[j]; \ - uint64_t anti_b = 0xffff - b; \ - int x = i_x + in_x1_int; \ - uint64_t output1r, output1g, output1b, output1a; \ - uint64_t output2r, output2g, output2b, output2a; \ - uint64_t output3r, output3g, output3b, output3a; \ - uint64_t output4r, output4g, output4b, output4a; \ - \ - output1r = in_row1[x * components]; \ - output1g = in_row1[x * components + 1]; \ - output1b = in_row1[x * components + 2]; \ - if(components == 4) output1a = in_row1[x * components + 3]; \ - \ - if(x < in_w_int - 1) \ - { \ - output2r = in_row1[x * components + components]; \ - output2g = in_row1[x * components + components + 1]; \ - output2b = in_row1[x * components + components + 2]; \ - if(components == 4) output2a = in_row1[x * components + components + 3]; \ - \ - if(in_row2) \ - { \ - output4r = in_row2[x * components + components]; \ - output4g = in_row2[x * components + components + 1]; \ - output4b = in_row2[x * components + components + 2]; \ - if(components == 4) output4a = in_row2[x * components + components + 3]; \ - } \ - else \ - { \ - output4r = zero_r; \ - output4g = zero_g; \ - output4b = zero_b; \ - if(components == 4) output4a = zero_a; \ - } \ - } \ - else \ - { \ - output2r = zero_r; \ - output2g = zero_g; \ - output2b = zero_b; \ - if(components == 4) output2a = zero_a; \ - output4r = zero_r; \ - output4g = zero_g; \ - output4b = zero_b; \ - if(components == 4) output4a = zero_a; \ - } \ - \ - if(in_row2) \ - { \ - output3r = in_row2[x * components]; \ - output3g = in_row2[x * components + 1]; \ - output3b = in_row2[x * components + 2]; \ - if(components == 4) output3a = in_row2[x * components + 3]; \ - } \ - else \ - { \ - output3r = zero_r; \ - output3g = zero_g; \ - output3b = zero_b; \ - if(components == 4) output3a = zero_a; \ - } \ - \ - out_row[j * components] = \ - (type)(((anti_a) * (((anti_b) * output1r) + \ - (b * output2r)) + \ - a * (((anti_b) * output3r) + \ - (b * output4r))) / 0xffffffff); \ - out_row[j * components + 1] = \ - (type)(((anti_a) * (((anti_b) * output1g) + \ - (b * output2g)) + \ - a * (((anti_b) * output3g) + \ - (b * output4g))) / 0xffffffff); \ - out_row[j * components + 2] = \ - (type)(((anti_a) * (((anti_b) * output1b) + \ - (b * output2b)) + \ - a * (((anti_b) * output3b) + \ - (b * output4b))) / 0xffffffff); \ - if(components == 4) \ - out_row[j * components + 3] = \ - (type)(((anti_a) * (((anti_b) * output1a) + \ - (b * output2a)) + \ - a * (((anti_b) * output3a) + \ - (b * output4a))) / 0xffffffff); \ - } \ - } \ - \ - \ - delete [] table_int_x; \ - delete [] table_frac_x; \ - delete [] table_int_y; \ - delete [] table_frac_y; \ - \ -} - - -#define BICUBIC(max, type, components) \ -{ \ - float k_y = 1.0 / scale_h; \ - float k_x = 1.0 / scale_w; \ - type **in_rows = (type**)input->get_rows(); \ - type **out_rows = (type**)output->get_rows(); \ - int *bspline_x, *bspline_y; \ - int in_h_int = input->get_h(); \ - int in_w_int = input->get_w(); \ - type zero_r, zero_g, zero_b, zero_a; \ - \ - zero_r = 0; \ - zero_b = ((max + 1) >> 1) * (do_yuv); \ - zero_g = ((max + 1) >> 1) * (do_yuv); \ - if(components == 4) \ - zero_a = 0; \ - \ - tabulate_bspline(bspline_x, \ - k_x, \ - out_w_int, \ - -1); \ - \ - tabulate_bspline(bspline_y, \ - k_y, \ - out_h_int, \ - 1); \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) \ - { \ - int i_y = (int)(k_y * i); \ - \ - \ - for(int j = 0; j < out_w_int; j++) \ - { \ - int i_x = (int)(k_x * j); \ - uint64_t output1, output2, output3, output4; \ - output1 = 0; \ - output2 = 0; \ - output3 = 0; \ - if(components == 4) \ - output4 = 0; \ - int table_y = i * 4; \ - \ -/* Kernel */ \ - for(int m = -1; m < 3; m++) \ - { \ - uint64_t r1 = bspline_y[table_y++]; \ - int y = in_y1_int + i_y + m; \ - int table_x = j * 4; \ - \ - for(int n = -1; n < 3; n++) \ - { \ - uint64_t r2 = bspline_x[table_x++]; \ - int x = in_x1_int + i_x + n; \ - uint64_t r_square = r1 * r2; \ - \ -/* Inside boundary. */ \ - if(x >= 0 && \ - x < in_w_int && \ - y >= 0 && \ - y < in_h_int) \ - { \ - output1 += r_square * in_rows[y][x * components]; \ - output2 += r_square * in_rows[y][x * components + 1]; \ - output3 += r_square * in_rows[y][x * components + 2]; \ - if(components == 4) \ - output4 += r_square * in_rows[y][x * components + 3]; \ - } \ - else \ - { \ - output1 += r_square * zero_r; \ - output2 += r_square * zero_g; \ - output3 += r_square * zero_b; \ - if(components == 4) \ - output4 += r_square * zero_a; \ - } \ - } \ - } \ - \ - \ - out_rows[i][j * components] = (type)(output1 / 0xffffffff); \ - out_rows[i][j * components + 1] = (type)(output2 / 0xffffffff); \ - out_rows[i][j * components + 2] = (type)(output3 / 0xffffffff); \ - if(components == 4) \ - out_rows[i][j * components + 3] = (type)(output4 / 0xffffffff); \ - \ - } \ - } \ - \ - delete [] bspline_x; \ - delete [] bspline_y; \ -} - - - - -// Pow function is not thread safe in Compaqt C -#define CUBE(x) ((x) * (x) * (x)) - -int ScaleUnit::cubic_bspline(float x) -{ - float a, b, c, d; - - if((x + 2.0F) <= 0.0F) - { - a = 0.0F; - } - else - { - a = CUBE(x + 2.0F); - } - - - if((x + 1.0F) <= 0.0F) - { - b = 0.0F; - } - else - { - b = CUBE(x + 1.0F); - } - - if(x <= 0) - { - c = 0.0F; - } - else - { - c = CUBE(x); - } - - if((x - 1.0F) <= 0.0F) - { - d = 0.0F; - } - else - { - d = CUBE(x - 1.0F); - } - - - return (int)((a - (4.0F * b) + (6.0F * c) - (4.0F * d)) / 6.0 * 0x10000); -} - - -void ScaleUnit::tabulate_bspline(int* &table, - float scale, - int pixels, - float coefficient) -{ - table = new int[pixels * 4]; - for(int i = 0, j = 0; i < pixels; i++) - { - float f_x = (float)i * scale; - float a = f_x - floor(f_x); - - for(float m = -1; m < 3; m++) - { - table[j++] = cubic_bspline(coefficient * (m - a)); - } - - } -} - -void ScaleUnit::tabulate_blinear(int* &table_int, - int* &table_frac, - float scale, - int pixel1, - int pixel2) -{ - table_int = new int[pixel2 - pixel1]; - table_frac = new int[pixel2 - pixel1]; - - for(int i = pixel1, j = 0; i < pixel2; i++, j++) - { - float f_x = (float)i * scale; - int i_x = (int)floor(f_x); - int a = (int)((f_x - floor(f_x)) * 0xffff); - - table_int[j] = i_x; - table_frac[j] = a; - } -} - -void ScaleUnit::process_package(LoadPackage *package) -{ - ScalePackage *pkg = (ScalePackage*)package; - -// Arguments for macros - VFrame *output = overlay->scale_output; - VFrame *input = overlay->scale_input; - float scale_w = overlay->w_scale; - float scale_h = overlay->h_scale; - int in_x1_int = overlay->in_x1_int; - int in_y1_int = overlay->in_y1_int; - int out_h_int = overlay->out_h_int; - int out_w_int = overlay->out_w_int; - int do_yuv = - (overlay->scale_input->get_color_model() == BC_YUV888 || - overlay->scale_input->get_color_model() == BC_YUVA8888 || - overlay->scale_input->get_color_model() == BC_YUV161616 || - overlay->scale_input->get_color_model() == BC_YUVA16161616); - - if(overlay->interpolation_type == CUBIC_CUBIC || - (overlay->interpolation_type == CUBIC_LINEAR - && overlay->w_scale > 1 && - overlay->h_scale > 1)) - { - - switch(overlay->scale_input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - BICUBIC(0xff, unsigned char, 3); - break; - - case BC_RGBA8888: - case BC_YUVA8888: - BICUBIC(0xff, unsigned char, 4); - break; - - case BC_RGB161616: - case BC_YUV161616: - BICUBIC(0xffff, uint16_t, 3); - break; - - case BC_RGBA16161616: - case BC_YUVA16161616: - BICUBIC(0xffff, uint16_t, 4); - break; - } - } - else -// Perform bilinear scaling input -> scale_output - { - switch(overlay->scale_input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - BILINEAR(0xff, unsigned char, 3); - break; - - case BC_RGBA8888: - case BC_YUVA8888: - BILINEAR(0xff, unsigned char, 4); - break; - - case BC_RGB161616: - case BC_YUV161616: - BILINEAR(0xffff, uint16_t, 3); - break; - - case BC_RGBA16161616: - case BC_YUVA16161616: - BILINEAR(0xffff, uint16_t, 4); - break; - } - } - -} - - - - - - - - - - - - - -ScaleEngine::ScaleEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -ScaleEngine::~ScaleEngine() -{ -} - -void ScaleEngine::init_packages() -{ - for(int i = 0; i < total_packages; i++) - { - ScalePackage *package = (ScalePackage*)packages[i]; - package->out_row1 = overlay->out_h_int / total_packages * i; - package->out_row2 = package->out_row1 + overlay->out_h_int / total_packages; - - if(i >= total_packages - 1) - package->out_row2 = overlay->out_h_int; - } -} - -LoadClient* ScaleEngine::new_client() -{ - return new ScaleUnit(this, overlay); -} - -LoadPackage* ScaleEngine::new_package() -{ - return new ScalePackage; -} - - - - - - - - - - - - - -TranslatePackage::TranslatePackage() -{ -} - - - -TranslateUnit::TranslateUnit(TranslateEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; -} - -TranslateUnit::~TranslateUnit() -{ -} - - - -void TranslateUnit::translation_array(transfer_table* &table, - float out_x1, - float out_x2, - float in_x1, - float in_x2, - int in_total, - int out_total, - int &out_x1_int, - int &out_x2_int) -{ - int out_w_int; - float offset = out_x1 - in_x1; - - out_x1_int = (int)out_x1; - out_x2_int = MIN((int)ceil(out_x2), out_total); - out_w_int = out_x2_int - out_x1_int; - - table = new transfer_table[out_w_int]; - bzero(table, sizeof(transfer_table) * out_w_int); - - -//printf("OverlayFrame::translation_array 1 %f %f -> %f %f\n", in_x1, in_x2, out_x1, out_x2); - - float in_x = in_x1; - for(int out_x = out_x1_int; out_x < out_x2_int; out_x++) - { - transfer_table *entry = &table[out_x - out_x1_int]; - - entry->in_x1 = (int)in_x; - entry->in_x2 = (int)in_x + 1; - -// Get fraction of output pixel to fill - entry->output_fraction = 1; - - if(out_x1 > out_x) - { - entry->output_fraction -= out_x1 - out_x; - } - - if(out_x2 < out_x + 1) - { - entry->output_fraction = (out_x2 - out_x); - } - -// Advance in_x until out_x_fraction is filled - float out_x_fraction = entry->output_fraction; - float in_x_fraction = floor(in_x + 1) - in_x; - - if(out_x_fraction <= in_x_fraction) - { - entry->in_fraction1 = out_x_fraction; - entry->in_fraction2 = 0.0; - in_x += out_x_fraction; - } - else - { - entry->in_fraction1 = in_x_fraction; - in_x += out_x_fraction; - entry->in_fraction2 = in_x - floor(in_x); - } - -// Clip in_x - if(entry->in_x2 >= in_total) - { - entry->in_x2 = in_total - 1; - entry->in_fraction2 = 0.0; - } - - if(entry->in_x1 >= in_total) - { - entry->in_x1 = in_total - 1; - entry->in_fraction1 = 0.0; - } -// printf("OverlayFrame::translation_array 2 %d %d %d %f %f %f\n", -// out_x, -// entry->in_x1, -// entry->in_x2, -// entry->in_fraction1, -// entry->in_fraction2, -// entry->output_fraction); - } -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define TRANSLATE(max, type, components) \ -{ \ - \ - type **in_rows = (type**)input->get_rows(); \ - type **out_rows = (type**)output->get_rows(); \ - \ -/* printf("OverlayFrame::translate 1 %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", */ \ -/* (in_x1), in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2); */ \ - \ - unsigned int master_opacity = (int)(alpha * max + 0.5); \ - unsigned int master_transparency = max - master_opacity; \ - \ -/* printf("TRANSLATE %d\n", mode); */ \ - \ - for(int i = row1; i < row2; i++) \ - { \ - int in_y1 = y_table[i - out_y1_int].in_x1; \ - int in_y2 = y_table[i - out_y1_int].in_x2; \ - float y_fraction1 = y_table[i - out_y1_int].in_fraction1; \ - float y_fraction2 = y_table[i - out_y1_int].in_fraction2; \ - float y_output_fraction = y_table[i - out_y1_int].output_fraction; \ - type *in_row1 = in_rows[(in_y1)]; \ - type *in_row2 = in_rows[(in_y2)]; \ - type *out_row = out_rows[i]; \ - \ - for(int j = out_x1_int; j < out_x2_int; j++) \ - { \ - int in_x1 = x_table[j - out_x1_int].in_x1; \ - int in_x2 = x_table[j - out_x1_int].in_x2; \ - float x_fraction1 = x_table[j - out_x1_int].in_fraction1; \ - float x_fraction2 = x_table[j - out_x1_int].in_fraction2; \ - float x_output_fraction = x_table[j - out_x1_int].output_fraction; \ - type *output = &out_row[j * components]; \ - int input1, input2, input3, input4; \ - \ - input1 = (int)(in_row1[in_x1 * components] * x_fraction1 * y_fraction1 + \ - in_row1[in_x2 * components] * x_fraction2 * y_fraction1 + \ - in_row2[in_x1 * components] * x_fraction1 * y_fraction2 + \ - in_row2[in_x2 * components] * x_fraction2 * y_fraction2 + 0.5); \ - input2 = (int)(in_row1[in_x1 * components + 1] * x_fraction1 * y_fraction1 + \ - in_row1[in_x2 * components + 1] * x_fraction2 * y_fraction1 + \ - in_row2[in_x1 * components + 1] * x_fraction1 * y_fraction2 + \ - in_row2[in_x2 * components + 1] * x_fraction2 * y_fraction2 + 0.5); \ - input3 = (int)(in_row1[in_x1 * components + 2] * x_fraction1 * y_fraction1 + \ - in_row1[in_x2 * components + 2] * x_fraction2 * y_fraction1 + \ - in_row2[in_x1 * components + 2] * x_fraction1 * y_fraction2 + \ - in_row2[in_x2 * components + 2] * x_fraction2 * y_fraction2 + 0.5); \ - if(components == 4) \ - input4 = (int)(in_row1[in_x1 * components + 3] * x_fraction1 * y_fraction1 + \ - in_row1[in_x2 * components + 3] * x_fraction2 * y_fraction1 + \ - in_row2[in_x1 * components + 3] * x_fraction1 * y_fraction2 + \ - in_row2[in_x2 * components + 3] * x_fraction2 * y_fraction2 + 0.5); \ - \ - unsigned int opacity = (int)(master_opacity * \ - y_output_fraction * \ - x_output_fraction + 0.5); \ - unsigned int transparency = max - opacity; \ - \ -/* if(opacity != max) printf("TRANSLATE %x %d %d\n", opacity, j, i); */ \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - } \ - } \ -} - -void TranslateUnit::process_package(LoadPackage *package) -{ - TranslatePackage *pkg = (TranslatePackage*)package; - int out_y1_int; - int out_y2_int; - int out_x1_int; - int out_x2_int; - - -// Variables for TRANSLATE - VFrame *input = overlay->translate_input; - VFrame *output = overlay->translate_output; - float in_x1 = overlay->translate_in_x1; - float in_y1 = overlay->translate_in_y1; - float in_x2 = overlay->translate_in_x2; - float in_y2 = overlay->translate_in_y2; - float out_x1 = overlay->translate_out_x1; - float out_y1 = overlay->translate_out_y1; - float out_x2 = overlay->translate_out_x2; - float out_y2 = overlay->translate_out_y2; - float alpha = overlay->translate_alpha; - int row1 = pkg->out_row1; - int row2 = pkg->out_row2; - int mode = overlay->translate_mode; - - transfer_table *x_table; - transfer_table *y_table; - - translation_array(x_table, - out_x1, - out_x2, - in_x1, - in_x2, - input->get_w(), - output->get_w(), - out_x1_int, - out_x2_int); - translation_array(y_table, - out_y1, - out_y2, - in_y1, - in_y2, - input->get_h(), - output->get_h(), - out_y1_int, - out_y2_int); - - switch(overlay->translate_input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - TRANSLATE(0xff, unsigned char, 3); - break; - - case BC_RGBA8888: - case BC_YUVA8888: - TRANSLATE(0xff, unsigned char, 4); - break; - - case BC_RGB161616: - case BC_YUV161616: - TRANSLATE(0xffff, uint16_t, 3); - break; - - case BC_RGBA16161616: - case BC_YUVA16161616: - TRANSLATE(0xffff, uint16_t, 4); - break; - } - - delete [] x_table; - delete [] y_table; -} - - - - - - - - - - -TranslateEngine::TranslateEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -TranslateEngine::~TranslateEngine() -{ -} - -void TranslateEngine::init_packages() -{ - int out_y1_int = (int)overlay->translate_out_y1; - int out_y2_int = MIN((int)ceil(overlay->translate_out_y2), overlay->translate_output->get_h()); - int out_h = out_y2_int - out_y1_int; - - for(int i = 0; i < total_packages; i++) - { - TranslatePackage *package = (TranslatePackage*)packages[i]; - package->out_row1 = (int)(out_y1_int + out_h / - total_packages * - i); - package->out_row2 = (int)((float)package->out_row1 + - out_h / - total_packages); - if(i >= total_packages - 1) - package->out_row2 = out_y2_int; - } -} - -LoadClient* TranslateEngine::new_client() -{ - return new TranslateUnit(this, overlay); -} - -LoadPackage* TranslateEngine::new_package() -{ - return new TranslatePackage; -} - - - - - - - - -#define SCALE_TRANSLATE(max, type, components) \ -{ \ - int64_t opacity = (int)(alpha * max + 0.5); \ - int64_t transparency = max - opacity; \ - int out_w = out_x2 - out_x1; \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) \ - { \ - int in_y = y_table[i - out_y1]; \ - type *in_row = (type*)in_rows[in_y] + in_x1 * components; \ - type *out_row = (type*)out_rows[i] + out_x1 * components; \ - \ -/* X direction is scaled and requires a table lookup */ \ - if(out_w != in_x2 - in_x1) \ - { \ - for(int j = 0; j < out_w; j++) \ - { \ - int in_x = x_table[j]; \ - int input1, input2, input3, input4; \ - type *output = out_row + j * components; \ - \ - input1 = in_row[in_x * components]; \ - input2 = in_row[in_x * components + 1]; \ - input3 = in_row[in_x * components + 2]; \ - if(components == 4) \ - input4 = in_row[in_x * components + 3]; \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - } \ - } \ - else \ -/* X direction is not scaled */ \ - { \ - for(int j = 0; j < out_w; j++) \ - { \ - int input1, input2, input3, input4; \ - type *output = out_row + j * components; \ - \ - input1 = in_row[j * components]; \ - input2 = in_row[j * components + 1]; \ - input3 = in_row[j * components + 2]; \ - if(components == 4) \ - input4 = in_row[j * components + 3]; \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - } \ - } \ - } \ -} - - - -ScaleTranslateUnit::ScaleTranslateUnit(ScaleTranslateEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; - this->scale_translate = server; -} - -ScaleTranslateUnit::~ScaleTranslateUnit() -{ -} - -void ScaleTranslateUnit::scale_array(int* &table, - int out_x1, - int out_x2, - int in_x1, - int in_x2, - int is_x) -{ - float scale = (float)(out_x2 - out_x1) / (in_x2 - in_x1); - - table = new int[out_x2 - out_x1]; - - if(!is_x) - { - for(int i = 0; i < out_x2 - out_x1; i++) - { - table[i] = (int)((float)i / scale + in_x1); - } - } - else - { - for(int i = 0; i < out_x2 - out_x1; i++) - { - table[i] = (int)((float)i / scale); - } - } -} - - -void ScaleTranslateUnit::process_package(LoadPackage *package) -{ - ScaleTranslatePackage *pkg = (ScaleTranslatePackage*)package; - -// Args for NEAREST_NEIGHBOR_MACRO - VFrame *output = scale_translate->output; - VFrame *input = scale_translate->input; - int in_x1 = scale_translate->in_x1; - int in_y1 = scale_translate->in_y1; - int in_x2 = scale_translate->in_x2; - int in_y2 = scale_translate->in_y2; - int out_x1 = scale_translate->out_x1; - int out_y1 = scale_translate->out_y1; - int out_x2 = scale_translate->out_x2; - int out_y2 = scale_translate->out_y2; - float alpha = scale_translate->alpha; - int mode = scale_translate->mode; - - int *x_table; - int *y_table; - unsigned char **in_rows = input->get_rows(); - unsigned char **out_rows = output->get_rows(); - - scale_array(x_table, - out_x1, - out_x2, - in_x1, - in_x2, - 1); - scale_array(y_table, - out_y1, - out_y2, - in_y1, - in_y2, - 0); - - - switch(input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - SCALE_TRANSLATE(0xff, uint8_t, 3); - break; - - case BC_RGBA8888: - case BC_YUVA8888: - SCALE_TRANSLATE(0xff, uint8_t, 4); - break; - - - case BC_RGB161616: - case BC_YUV161616: - SCALE_TRANSLATE(0xffff, uint16_t, 3); - break; - - case BC_RGBA16161616: - case BC_YUVA16161616: - SCALE_TRANSLATE(0xffff, uint16_t, 4); - break; - } - - delete [] x_table; - delete [] y_table; - -}; - - - - - - - - - -ScaleTranslateEngine::ScaleTranslateEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -ScaleTranslateEngine::~ScaleTranslateEngine() -{ -} - -void ScaleTranslateEngine::init_packages() -{ - int out_h = out_y2 - out_y1; - - for(int i = 0; i < total_packages; i++) - { - ScaleTranslatePackage *package = (ScaleTranslatePackage*)packages[i]; - package->out_row1 = (int)(out_y1 + out_h / - total_packages * - i); - package->out_row2 = (int)((float)package->out_row1 + - out_h / - total_packages); - if(i >= total_packages - 1) - package->out_row2 = out_y2; - } -} - -LoadClient* ScaleTranslateEngine::new_client() -{ - return new ScaleTranslateUnit(this, overlay); -} - -LoadPackage* ScaleTranslateEngine::new_package() -{ - return new ScaleTranslatePackage; -} - - -ScaleTranslatePackage::ScaleTranslatePackage() -{ -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define BLEND_ONLY(type, max, components) \ -{ \ - int64_t opacity = (int)(alpha * max + 0.5); \ - int64_t transparency = max - opacity; \ - \ - type** output_rows = (type**)output->get_rows(); \ - type** input_rows = (type**)input->get_rows(); \ - int w = input->get_w(); \ - int h = input->get_h(); \ - \ - for(int i = pkg->out_row1; i < pkg->out_row2; i++) \ - { \ - type* in_row = input_rows[i]; \ - type* output = output_rows[i]; \ - \ - for(int j = 0; j < w; j++) \ - { \ - int input1, input2, input3, input4; \ - input1 = in_row[j * components]; \ - input2 = in_row[j * components + 1]; \ - input3 = in_row[j * components + 2]; \ - if(components == 4) input4 = in_row[j * components + 3]; \ - \ - \ - if(components == 3) \ - { \ - BLEND_3(max, type); \ - } \ - else \ - { \ - BLEND_4(max, type); \ - } \ - \ - input += components; \ - output += components; \ - } \ - } \ -} - - - - -BlendUnit::BlendUnit(BlendEngine *server, OverlayFrame *overlay) - : LoadClient(server) -{ - this->overlay = overlay; - this->blend_engine = server; -} - -BlendUnit::~BlendUnit() -{ -} - -void BlendUnit::process_package(LoadPackage *package) -{ - BlendPackage *pkg = (BlendPackage*)package; - - - VFrame *output = blend_engine->output; - VFrame *input = blend_engine->input; - float alpha = blend_engine->alpha; - int mode = blend_engine->mode; - - switch(input->get_color_model()) - { - case BC_RGB888: - case BC_YUV888: - BLEND_ONLY(unsigned char, 0xff, 3); - break; - case BC_RGBA8888: - case BC_YUVA8888: - BLEND_ONLY(unsigned char, 0xff, 4); - break; - case BC_RGB161616: - case BC_YUV161616: - BLEND_ONLY(uint16_t, 0xffff, 3); - break; - case BC_RGBA16161616: - case BC_YUVA16161616: - BLEND_ONLY(uint16_t, 0xffff, 4); - break; - } -} - - - -BlendEngine::BlendEngine(OverlayFrame *overlay, int cpus) - : LoadServer(cpus, cpus) -{ - this->overlay = overlay; -} - -BlendEngine::~BlendEngine() -{ -} - -void BlendEngine::init_packages() -{ - for(int i = 0; i < total_packages; i++) - { - BlendPackage *package = (BlendPackage*)packages[i]; - package->out_row1 = (int)(input->get_h() / - total_packages * - i); - package->out_row2 = (int)((float)package->out_row1 + - input->get_h() / - total_packages); - - if(i >= total_packages - 1) - package->out_row2 = input->get_h(); - } -} - -LoadClient* BlendEngine::new_client() -{ - return new BlendUnit(this, overlay); -} - -LoadPackage* BlendEngine::new_package() -{ - return new BlendPackage; -} - - -BlendPackage::BlendPackage() -{ -} - - diff --git a/cinelerra-5.1/cinelerra/overlayframe.h b/cinelerra-5.1/cinelerra/overlayframe.h index 7ca03621..730be374 100644 --- a/cinelerra-5.1/cinelerra/overlayframe.h +++ b/cinelerra-5.1/cinelerra/overlayframe.h @@ -24,13 +24,351 @@ #include "loadbalance.h" #include "overlayframe.inc" -#include "vframe.inc" +#include "vframe.h" + +#include +#include +#include +#include +#include +#include #define DIRECT_COPY 0 #define BILINEAR 1 #define BICUBIC 2 #define LANCZOS 3 +#define STD_ALPHA(mx, Sa, Da) (Sa + Da - (Sa * Da) / mx) +#define STD_BLEND(mx, Sc, Sa, Dc, Da) ((Sc * (mx - Da) + Dc * (mx - Sa)) / mx) + +#define ZERO 0 +#define ONE 1 +#define TWO 2 + +// 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) +#define CHROMA_NORMAL COLOR_NORMAL + +// ADDITION [(Sa + Da), (Sc + Dc)] +#define ALPHA_ADDITION(mx, Sa, Da) (Sa + Da) +#define COLOR_ADDITION(mx, Sc, Sa, Dc, Da) (Sc + Dc) +#define CHROMA_ADDITION COLOR_ADDITION + +// SUBTRACT [(Sa - Da), (Sc - Dc)] +#define ALPHA_SUBTRACT(mx, Sa, Da) (Sa - Da) +#define COLOR_SUBTRACT(mx, Sc, Sa, Dc, Da) (Sc - Dc) +#define CHROMA_SUBTRACT COLOR_SUBTRACT + +// MULTIPLY [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + Sc * Dc] +#define ALPHA_MULTIPLY STD_ALPHA +#define COLOR_MULTIPLY(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \ + (Sc * Dc) / mx) +#define CHROMA_MULTIPLY COLOR_MULTIPLY + +// DIVIDE [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + Sc / Dc] +#define ALPHA_DIVIDE STD_ALPHA +#define COLOR_DIVIDE(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \ + (Dc > ZERO ? (Sc * mx) / Dc : ZERO)) +#define CHROMA_DIVIDE COLOR_DIVIDE + +// REPLACE [Sa, Sc] (fade = 1) +#define ALPHA_REPLACE(mx, Sa, Da) Sa +#define COLOR_REPLACE(mx, Sc, Sa, Dc, Da) Sc +#define CHROMA_REPLACE COLOR_REPLACE + +// MAX [max(Sa, Da), MAX(Sc, Dc)] +#define ALPHA_MAX(mx, Sa, Da) (Sa > Da ? Sa : Da) +#define COLOR_MAX(mx, Sc, Sa, Dc, Da) (Sc > Dc ? Sc : Dc) +#define CHROMA_MAX(mx, Sc, Sa, Dc, Da) (mabs(Sc) > mabs(Dc) ? Sc : Dc) + +// MIN [min(Sa, Da), MIN(Sc, Dc)] +#define ALPHA_MIN(mx, Sa, Da) (Sa < Da ? Sa : Da) +#define COLOR_MIN(mx, Sc, Sa, Dc, Da) (Sc < Dc ? Sc : Dc) +#define CHROMA_MIN(mx, Sc, Sa, Dc, Da) (mabs(Sc) < mabs(Dc) ? Sc : Dc) + +// DARKEN [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc*Da, Dc*Sa)] +#define ALPHA_DARKEN STD_ALPHA +#define COLOR_DARKEN(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \ + mmin(Sc * Da, Dc * Sa) / mx) +#define CHROMA_DARKEN(mx, Sc, Sa, Dc, Da) (CHROMA_XOR(mx,Sc,Sa,Dc,Da) + \ + (mabs(Sc * Da) < mabs(Dc * Sa) ? Sc * Da : Dc * Sa) / mx) + +// LIGHTEN [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc*Da, Dc*Sa)] +#define ALPHA_LIGHTEN STD_ALPHA +#define COLOR_LIGHTEN(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \ + mmax(Sc * Da, Dc * Sa) / mx) +#define CHROMA_LIGHTEN(mx, Sc, Sa, Dc, Da) (CHROMA_XOR(mx,Sc,Sa,Dc,Da) + \ + (mabs(Sc * Da) > mabs(Dc * Sa) ? Sc * Da : Dc * Sa) / mx) + +// DST [Da, Dc] +#define ALPHA_DST(mx, Sa, Da) Da +#define COLOR_DST(mx, Sc, Sa, Dc, Da) Dc +#define CHROMA_DST COLOR_DST + +// DST_ATOP [Sa, Sc * (1 - Da) + Dc * Sa] +#define ALPHA_DST_ATOP(mx, Sa, Da) Sa +#define COLOR_DST_ATOP(mx, Sc, Sa, Dc, Da) ((Sc * (mx - Da) + Dc * Sa) / mx) +#define CHROMA_DST_ATOP COLOR_DST_ATOP + +// DST_IN [Da * Sa, Dc * Sa] +#define ALPHA_DST_IN(mx, Sa, Da) ((Da * Sa) / mx) +#define COLOR_DST_IN(mx, Sc, Sa, Dc, Da) ((Dc * Sa) / mx) +#define CHROMA_DST_IN COLOR_DST_IN + +// DST_OUT [Da * (1 - Sa), Dc * (1 - Sa)] +#define ALPHA_DST_OUT(mx, Sa, Da) (Da * (mx - Sa) / mx) +#define COLOR_DST_OUT(mx, Sc, Sa, Dc, Da) (Dc * (mx - Sa) / mx) +#define CHROMA_DST_OUT COLOR_DST_OUT + +// DST_OVER [Sa + Da - Sa*Da, Sc * (1 - Da) + Dc] +#define ALPHA_DST_OVER STD_ALPHA +#define COLOR_DST_OVER(mx, Sc, Sa, Dc, Da) (Sc * (mx - Da)/ mx + Dc) +#define CHROMA_DST_OVER COLOR_DST_OVER + +// SRC [Sa, Sc] +#define ALPHA_SRC(mx, Sa, Da) Sa +#define COLOR_SRC(mx, Sc, Sa, Dc, Da) Sc +#define CHROMA_SRC COLOR_SRC + +// SRC_ATOP [Da, Sc * Da + Dc * (1 - Sa)] +#define ALPHA_SRC_ATOP(mx, Sa, Da) Da +#define COLOR_SRC_ATOP(mx, Sc, Sa, Dc, Da) ((Sc * Da + Dc * (mx - Sa)) / mx) +#define CHROMA_SRC_ATOP COLOR_SRC_ATOP + +// SRC_IN [Sa * Da, Sc * Da] +#define ALPHA_SRC_IN(mx, Sa, Da) ((Sa * Da) / mx) +#define COLOR_SRC_IN(mx, Sc, Sa, Dc, Da) (Sc * Da / mx) +#define CHROMA_SRC_IN COLOR_SRC_IN + +// SRC_OUT [Sa * (1 - Da), Sc * (1 - Da)] +#define ALPHA_SRC_OUT(mx, Sa, Da) (Sa * (mx - Da) / mx) +#define COLOR_SRC_OUT(mx, Sc, Sa, Dc, Da) (Sc * (mx - Da) / mx) +#define CHROMA_SRC_OUT COLOR_SRC_OUT + +// SRC_OVER [Sa + Da - Sa*Da, Sc + (1 - Sa) * Dc] +#define ALPHA_SRC_OVER STD_ALPHA +#define COLOR_SRC_OVER(mx, Sc, Sa, Dc, Da) (Sc + Dc * (mx - Sa) / mx) +#define CHROMA_SRC_OVER COLOR_SRC_OVER + +// AND [Sa + Da - Sa * Da, Sc * Dc] +#define ALPHA_AND(mx, Sa, Da) ((Sa * Da) / mx) +#define COLOR_AND(mx, Sc, Sa, Dc, Da) ((Sc * Dc) / mx) +#define CHROMA_AND COLOR_AND + +// OR [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] +#define ALPHA_OR(mx, Sa, Da) (Sa + Da - (Sa * Da) / mx) +#define COLOR_OR(mx, Sc, Sa, Dc, Da) (Sc + Dc - (Sc * Dc) / mx) +#define CHROMA_OR COLOR_OR + +// XOR [Sa * (1 - Da) + Da * (1 - Sa), Sa + Da - 2 * Sa * Da] +#define ALPHA_XOR(mx, Sa, Da) (Sa + Da - (TWO * Sa * Da / mx)) +#define COLOR_XOR(mx, Sc, Sa, Dc, Da) ((Sc * (mx - Da) + Dc * (mx - Sa)) / mx) +#define CHROMA_XOR COLOR_XOR + +//SVG 1.2 +//https://www.w3.org/TR/2004/WD-SVG12-20041027/rendering.html +// OVERLAY [Sa + Da - Sa * Da, Sc*(1 - Da) + Dc*(1 - Sa) + +// 2*Dc < Da ? 2*Sc*Dc : Sa*Da - 2*(Da-Dc)*(Sa-Sc) ] +#define ALPHA_OVERLAY STD_ALPHA +#define COLOR_OVERLAY(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \ + ((TWO * Dc < Da) ? \ + (TWO * Sc * Dc) : (Sa * Da - TWO * (Da - Dc) * (Sa - Sc))) / mx) +#define CHROMA_OVERLAY COLOR_OVERLAY + +// SCREEN [Sa + Da - Sa * Da, Sc + Dc - (Sc * Dc)] (same as OR) +#define ALPHA_SCREEN STD_ALPHA +#define COLOR_SCREEN(mx, Sc, Sa, Dc, Da) (Sc + Dc - (Sc * Dc) / mx) +#define CHROMA_SCREEN COLOR_SCREEN + +// BURN [Sa + Da - Sa * Da, Sc*(1 - Da) + Dc*(1 - Sa) + +// Sc <= 0 || Sc*Da + Dc*Sa <= Sa*Da ? 0 : (Sc*Da + Dc*Sa - Sa*Da)*Sa/Sc] +#define ALPHA_BURN STD_ALPHA +#define COLOR_BURN(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \ + ((Sc <= ZERO || Sc * Da + Dc * Sa <= Sa * Da) ? ZERO : \ + (Sa * ((Sc * Da + Dc * Sa - Sa * Da) / Sc) / mx))) +#define CHROMA_BURN COLOR_BURN + +// DODGE [Sa + Da - Sa * Da, Sc*(1 - Da) + Dc*(1 - Sa) + +// Sa <= Sc || Sc*Da + Dc*Sa >= Sa*Da) ? Sa*Da : Dc*Sa / (1 - Sc/Sa)] +#define ALPHA_DODGE STD_ALPHA +#define COLOR_DODGE(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \ + ((Sa <= Sc || Sc * Da + Dc * Sa >= Sa * Da) ? (Sa * Da) : \ + (Sa * ((Dc * Sa) / (Sa - Sc))) / mx)) +#define CHROMA_DODGE COLOR_DODGE + +// HARDLIGHT [Sa + Da - Sa * Da, Sc*(1 - Da) + Dc*(1 - Sa) + +// 2*Sc < Sa ? 2*Sc*Dc : Sa*Da - 2*(Da - Dc)*(Sa - Sc)] +#define ALPHA_HARDLIGHT STD_ALPHA +#define COLOR_HARDLIGHT(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \ + ((TWO * Sc < Sa) ? \ + (TWO * Sc * Dc) : (Sa * Da - TWO * (Da - Dc) * (Sa - Sc))) / mx) +#define CHROMA_HARDLIGHT COLOR_HARDLIGHT + +// SOFTLIGHT [Sa + Da - Sa * Da, Sc*(1 - Da) + Dc*(1 - Sa) + +// Da > 0 ? (Dc*Sa + 2*Sc*(Da - Dc))/Da : 0] +#define ALPHA_SOFTLIGHT STD_ALPHA +#define COLOR_SOFTLIGHT(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \ + ((Da > ZERO) ? \ + (Dc * ((Dc*Sa + TWO * Sc * (Da - Dc)) / Da) / mx) : ZERO)) +#define CHROMA_SOFTLIGHT COLOR_SOFTLIGHT + +// DIFFERENCE [Sa + Da - Sa * Da, Sc*(1 - Da) + Dc*(1 - Sa) + +// abs(Sc * Da - Sc * Sa)] +#define ALPHA_DIFFERENCE STD_ALPHA +#define COLOR_DIFFERENCE(mx, Sc, Sa, Dc, Da) (STD_BLEND(mx,Sc,Sa,Dc,Da) + \ + (mabs(Sc * Da - Dc * Sa) / mx)) +#define CHROMA_DIFFERENCE COLOR_DIFFERENCE + +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); } +static inline int mmin(int32_t a, int32_t b) { return a < b ? a : b; } +static inline int mmin(int64_t a, int64_t b) { return a < b ? a : b; } +static inline float mmin(float a, float b) { return a < b ? a : b; } +static inline int mmax(int32_t a, int32_t b) { return a > b ? a : b; } +static inline int mmax(int64_t a, int64_t b) { return a > b ? a : b; } +static inline float mmax(float a, float b) { return a > b ? a : b; } + +static inline int32_t aclip(int32_t v, int mx) { + return v < 0 ? 0 : v > mx ? mx : v; +} +static inline int64_t aclip(int64_t v, int mx) { + return v < 0 ? 0 : v > mx ? mx : v; +} +static inline float aclip(float v, float mx) { + return v < 0 ? 0 : v > mx ? mx : v; +} +static inline float aclip(float v, int mx) { + return v < 0 ? 0 : v > mx ? mx : v; +} +static inline int aclip(int v, float mx) { + return v < 0 ? 0 : v > mx ? mx : v; +} +static inline int32_t cclip(int32_t v, int mx) { + return v > (mx/=2) ? mx : v < (mx=(-mx-1)) ? mx : v; +} +static inline int64_t cclip(int64_t v, int mx) { + return v > (mx/=2) ? mx : v < (mx=(-mx-1)) ? mx : v; +} +static inline float cclip(float v, float mx) { + return v > (mx/=2) ? mx : v < (mx=(-mx)) ? mx : v; +} +static inline float cclip(float v, int mx) { + return v > (mx/=2) ? mx : v < (mx=(-mx-1)) ? mx : v; +} +static inline int cclip(int v, float mx) { + return v > (mx/=2) ? mx : v < (mx=(-mx-1)) ? mx : v; +} + +/* number of data pts per unit x in lookup table */ +#define TRANSFORM_SPP (4096) +/* bits of fraction past TRANSFORM_SPP on kernel index accumulation */ +#define INDEX_FRACTION (8) +#define TRANSFORM_MIN (.5 / TRANSFORM_SPP) + +#define ZTYP(ty) typedef ty z_##ty __attribute__ ((__unused__)) +ZTYP(int8_t); ZTYP(uint8_t); +ZTYP(int16_t); ZTYP(uint16_t); +ZTYP(int32_t); ZTYP(uint32_t); +ZTYP(int64_t); ZTYP(uint64_t); +ZTYP(float); ZTYP(double); + +#define ALPHA3_BLEND(FN, typ, inp, out, mx, iofs, oofs, rnd) \ + typ inp0 = (typ)inp[0], inp1 = (typ)inp[1] - iofs; \ + typ inp2 = (typ)inp[2] - iofs, inp3 = mx; \ + typ out0 = (typ)out[0], out1 = (typ)out[1] - oofs; \ + typ out2 = (typ)out[2] - oofs, out3 = mx; \ + r = COLOR_##FN(mx, inp0, inp3, out0, out3); \ + if( oofs ) { \ + g = CHROMA_##FN(mx, inp1, inp3, out1, out3); \ + b = CHROMA_##FN(mx, inp2, inp3, out2, out3); \ + } \ + else { \ + g = COLOR_##FN(mx, inp1, inp3, out1, out3); \ + b = COLOR_##FN(mx, inp2, inp3, out2, out3); \ + } + +#define ALPHA4_BLEND(FN, typ, inp, out, mx, iofs, oofs, rnd) \ + typ inp0 = (typ)inp[0], inp1 = (typ)inp[1] - iofs; \ + typ inp2 = (typ)inp[2] - iofs, inp3 = inp[3]; \ + typ out0 = (typ)out[0], out1 = (typ)out[1] - oofs; \ + typ out2 = (typ)out[2] - oofs, out3 = out[3]; \ + r = COLOR_##FN(mx, inp0, inp3, out0, out3); \ + if( oofs ) { \ + g = CHROMA_##FN(mx, inp1, inp3, out1, out3); \ + b = CHROMA_##FN(mx, inp2, inp3, out2, out3); \ + } \ + else { \ + g = COLOR_##FN(mx, inp1, inp3, out1, out3); \ + b = COLOR_##FN(mx, inp2, inp3, out2, out3); \ + } \ + a = ALPHA_##FN(mx, inp3, out3) + +#define ALPHA_STORE(out, ofs, mx) \ + out[0] = r; \ + out[1] = g + ofs; \ + out[2] = b + ofs + +#define ALPHA3_STORE(out, ofs, mx) \ + r = aclip(r, mx); \ + g = ofs ? cclip(g, mx) : aclip(g, mx); \ + b = ofs ? cclip(b, mx) : aclip(b, mx); \ + if( trnsp ) { \ + r = (r * opcty + out0 * trnsp) / mx; \ + g = (g * opcty + out1 * trnsp) / mx; \ + b = (b * opcty + out2 * trnsp) / mx; \ + } \ + ALPHA_STORE(out, ofs, mx) + +#define ALPHA4_STORE(out, ofs, mx) \ + r = aclip(r, mx); \ + g = ofs ? cclip(g, mx) : aclip(g, mx); \ + b = ofs ? cclip(b, mx) : aclip(b, mx); \ + if( trnsp ) { \ + r = (r * opcty + out0 * trnsp) / mx; \ + g = (g * opcty + out1 * trnsp) / mx; \ + b = (b * opcty + out2 * trnsp) / mx; \ + a = (a * opcty + out3 * trnsp) / mx; \ + } \ + ALPHA_STORE(out, ofs, mx); \ + out[3] = aclip(a, mx) + + +#define BLEND_SWITCH(FN) \ + switch( mode ) { \ + case TRANSFER_NORMAL: FN(NORMAL); \ + case TRANSFER_ADDITION: FN(ADDITION); \ + case TRANSFER_SUBTRACT: FN(SUBTRACT); \ + case TRANSFER_MULTIPLY: FN(MULTIPLY); \ + case TRANSFER_DIVIDE: FN(DIVIDE); \ + case TRANSFER_REPLACE: FN(REPLACE); \ + case TRANSFER_MAX: FN(MAX); \ + case TRANSFER_MIN: FN(MIN); \ + case TRANSFER_DARKEN: FN(DARKEN); \ + case TRANSFER_LIGHTEN: FN(LIGHTEN); \ + case TRANSFER_DST: FN(DST); \ + case TRANSFER_DST_ATOP: FN(DST_ATOP); \ + case TRANSFER_DST_IN: FN(DST_IN); \ + case TRANSFER_DST_OUT: FN(DST_OUT); \ + case TRANSFER_DST_OVER: FN(DST_OVER); \ + case TRANSFER_SRC: FN(SRC); \ + case TRANSFER_SRC_ATOP: FN(SRC_ATOP); \ + case TRANSFER_SRC_IN: FN(SRC_IN); \ + case TRANSFER_SRC_OUT: FN(SRC_OUT); \ + case TRANSFER_SRC_OVER: FN(SRC_OVER); \ + case TRANSFER_AND: FN(AND); \ + case TRANSFER_OR: FN(OR); \ + case TRANSFER_XOR: FN(XOR); \ + case TRANSFER_OVERLAY: FN(OVERLAY); \ + case TRANSFER_SCREEN: FN(SCREEN); \ + case TRANSFER_BURN: FN(BURN); \ + case TRANSFER_DODGE: FN(DODGE); \ + case TRANSFER_HARDLIGHT: FN(HARDLIGHT); \ + case TRANSFER_SOFTLIGHT: FN(SOFTLIGHT); \ + case TRANSFER_DIFFERENCE: FN(DIFFERENCE); \ + } + class OverlayKernel { public: diff --git a/cinelerra-5.1/cinelerra/overlayframe.h.clamp b/cinelerra-5.1/cinelerra/overlayframe.h.clamp deleted file mode 100644 index 4df7207b..00000000 --- a/cinelerra-5.1/cinelerra/overlayframe.h.clamp +++ /dev/null @@ -1,381 +0,0 @@ -#ifndef OVERLAYFRAME_H -#define OVERLAYFRAME_H - -#include "loadbalance.h" -#include "overlayframe.inc" -#include "vframe.inc" - - -// Issues encoutered with overlay - -// Floating point vs. int. On alpha the floating point interpolation is about -// 2x faster than integer interpolation. Integer interpolation uses 32 -// siginificant bits while floating point uses 24, however. - -// Single step vs. two step process. - -// A single step process would require performing blend with the output -// of BILINEAR or BICUBIC and trimming the output to fractional pixels. -// This is easy. - -// However reading the input for -// BILINEAR and BICUBIC would require trimming the input to fractional -// pixels often repeatedly since the interpolation reads the same pixels more -// than once. This is hard. - -// In the two step process one step worries purely about scaling, ignoring -// trimming at the input and output so redundant trimming is not done here. - -// The translation engine focuses purely on trimming input pixels and -// blending with the output. - -// Translation - -typedef struct -{ - int in_x1; - float in_fraction1; - int in_x2; // Might be same as in_x1 for boundary - float in_fraction2; - float output_fraction; -} transfer_table; - - -class ScaleEngine; - -class ScalePackage : public LoadPackage -{ -public: - ScalePackage(); - - int out_row1, out_row2; -}; - -class ScaleUnit : public LoadClient -{ -public: - ScaleUnit(ScaleEngine *server, OverlayFrame *overlay); - ~ScaleUnit(); - - float cubic_bspline(float x); - void tabulate_bicubic(float* &coef_table, - int* &coord_table, - float scale, - int start, - int pixels, - int total_pixels, - float coefficient); - void tabulate_blinear(int* &table_int1, - int* &table_int2, - float* &table_frac, - float* &table_antifrac, - float scale, - int pixel1, - int pixel2, - int start, - int total_pixels); - - void process_package(LoadPackage *package); - - OverlayFrame *overlay; - ScaleEngine *engine; -}; - -class ScaleEngine : public LoadServer -{ -public: - ScaleEngine(OverlayFrame *overlay, int cpus); - ~ScaleEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; -// Global parameters for scaling units - VFrame *scale_output; - VFrame *scale_input; - float w_scale; - float h_scale; - int in_x1_int; - int in_y1_int; - int out_w_int; - int out_h_int; - int interpolation_type; -}; - - - - - - - -class TranslateEngine; - -class TranslatePackage : public LoadPackage -{ -public: - TranslatePackage(); - - int out_row1, out_row2; -}; - - -class TranslateUnit : public LoadClient -{ -public: - TranslateUnit(TranslateEngine *server, OverlayFrame *overlay); - ~TranslateUnit(); - - void process_package(LoadPackage *package); - void translation_array(transfer_table* &table, - float out_x1, - float out_x2, - float in_x1, - float in_x2, - int in_total, - int out_total, - int &out_x1_int, - int &out_x2_int); - void translate(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, - int mode, - int row1, - int row2); - - OverlayFrame *overlay; - TranslateEngine *engine; -}; - -class TranslateEngine : public LoadServer -{ -public: - TranslateEngine(OverlayFrame *overlay, int cpus); - ~TranslateEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; -// Global parameters for translate units - VFrame *translate_output; - VFrame *translate_input; - float translate_in_x1; - float translate_in_y1; - float translate_in_x2; - float translate_in_y2; - float translate_out_x1; - float translate_out_y1; - float translate_out_x2; - float translate_out_y2; - float translate_alpha; - int translate_mode; -}; - - - - - - - - - -class ScaleTranslateEngine; - -class ScaleTranslatePackage : public LoadPackage -{ -public: - ScaleTranslatePackage(); - - int out_row1, out_row2; -}; - - -class ScaleTranslateUnit : public LoadClient -{ -public: - ScaleTranslateUnit(ScaleTranslateEngine *server, OverlayFrame *overlay); - ~ScaleTranslateUnit(); - - void process_package(LoadPackage *package); - void scale_array(int* &table, - int out_x1, - int out_x2, - int in_x1, - int in_x2, - int is_x); - - OverlayFrame *overlay; - ScaleTranslateEngine *scale_translate; -}; - -class ScaleTranslateEngine : public LoadServer -{ -public: - ScaleTranslateEngine(OverlayFrame *overlay, int cpus); - ~ScaleTranslateEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; - - -// Arguments - VFrame *output; - VFrame *input; - int in_x1; - int in_y1; - int in_x2; - int in_y2; - int out_x1; - int out_y1; - int out_x2; - int out_y2; - float alpha; - int mode; -}; - - - - - - - - - - - - - - - -class BlendEngine; - -class BlendPackage : public LoadPackage -{ -public: - BlendPackage(); - - int out_row1, out_row2; -}; - - -class BlendUnit : public LoadClient -{ -public: - BlendUnit(BlendEngine *server, OverlayFrame *overlay); - ~BlendUnit(); - - void process_package(LoadPackage *package); - void translation_array(transfer_table* &table, - float out_x1, - float out_x2, - float in_x1, - float in_x2, - int in_total, - int out_total, - int &out_x1_int, - int &out_x2_int); - void translate(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, - int mode, - int row1, - int row2); - - OverlayFrame *overlay; - BlendEngine *blend_engine; -}; - -class BlendEngine : public LoadServer -{ -public: - BlendEngine(OverlayFrame *overlay, int cpus); - ~BlendEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; - - -// Arguments - VFrame *output; - VFrame *input; - float alpha; - int mode; -}; - - - - - - - - - - - - - -class OverlayFrame -{ -public: - OverlayFrame(int cpus = 1); - virtual ~OverlayFrame(); - -// Alpha is from 0 - 1 - int overlay(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, - int mode, - int interpolation_type); - - int overlay(VFrame *output, unsigned char *input, - float in_x1, float in_y1, float in_x2, float in_y2, - float out_x1, float out_y1, float out_x2, float out_y2, - int alpha, int in_w, int in_h); - int use_alpha, use_float, mode, interpolate; - int color_model; - - BlendEngine *blend_engine; - ScaleEngine *scale_engine; - TranslateEngine *translate_engine; - ScaleTranslateEngine *scaletranslate_engine; - - - VFrame *temp_frame; - int cpus; - -}; - -#endif diff --git a/cinelerra-5.1/cinelerra/overlayframe.h.float b/cinelerra-5.1/cinelerra/overlayframe.h.float deleted file mode 100644 index cf1f30e6..00000000 --- a/cinelerra-5.1/cinelerra/overlayframe.h.float +++ /dev/null @@ -1,347 +0,0 @@ -#ifndef OVERLAYFRAME_H -#define OVERLAYFRAME_H - -#include "loadbalance.h" -#include "overlayframe.inc" -#include "vframe.inc" - - - -// Translation - -typedef struct -{ - int in_x1; - float in_fraction1; - int in_x2; // Might be same as in_x1 for boundary - float in_fraction2; - float output_fraction; -} transfer_table; - - -class ScaleEngine; - -class ScalePackage : public LoadPackage -{ -public: - ScalePackage(); - - int out_row1, out_row2; -}; - - -class ScaleUnit : public LoadClient -{ -public: - ScaleUnit(ScaleEngine *server, OverlayFrame *overlay); - ~ScaleUnit(); - - float cubic_bspline(float x); - void tabulate_bspline(float* &table, - float scale, - int pixels, - float coefficient); - - void process_package(LoadPackage *package); - - OverlayFrame *overlay; -}; - -class ScaleEngine : public LoadServer -{ -public: - ScaleEngine(OverlayFrame *overlay, int cpus); - ~ScaleEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; -}; - - - - - - - -class TranslateEngine; - -class TranslatePackage : public LoadPackage -{ -public: - TranslatePackage(); - - int out_row1, out_row2; -}; - - -class TranslateUnit : public LoadClient -{ -public: - TranslateUnit(TranslateEngine *server, OverlayFrame *overlay); - ~TranslateUnit(); - - void process_package(LoadPackage *package); - void translation_array(transfer_table* &table, - float out_x1, - float out_x2, - float in_x1, - float in_x2, - int in_total, - int out_total, - int &out_x1_int, - int &out_x2_int); - void translate(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, - int mode, - int row1, - int row2); - - OverlayFrame *overlay; -}; - -class TranslateEngine : public LoadServer -{ -public: - TranslateEngine(OverlayFrame *overlay, int cpus); - ~TranslateEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; -}; - - - - - - - - - -class ScaleTranslateEngine; - -class ScaleTranslatePackage : public LoadPackage -{ -public: - ScaleTranslatePackage(); - - int out_row1, out_row2; -}; - - -class ScaleTranslateUnit : public LoadClient -{ -public: - ScaleTranslateUnit(ScaleTranslateEngine *server, OverlayFrame *overlay); - ~ScaleTranslateUnit(); - - void process_package(LoadPackage *package); - void scale_array(int* &table, - int out_x1, - int out_x2, - int in_x1, - int in_x2, - int is_x); - - OverlayFrame *overlay; - ScaleTranslateEngine *scale_translate; -}; - -class ScaleTranslateEngine : public LoadServer -{ -public: - ScaleTranslateEngine(OverlayFrame *overlay, int cpus); - ~ScaleTranslateEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; - - -// Arguments - VFrame *output; - VFrame *input; - int in_x1; - int in_y1; - int in_x2; - int in_y2; - int out_x1; - int out_y1; - int out_x2; - int out_y2; - float alpha; - int mode; -}; - - - - - - - - - - - - - - - -class BlendEngine; - -class BlendPackage : public LoadPackage -{ -public: - BlendPackage(); - - int out_row1, out_row2; -}; - - -class BlendUnit : public LoadClient -{ -public: - BlendUnit(BlendEngine *server, OverlayFrame *overlay); - ~BlendUnit(); - - void process_package(LoadPackage *package); - void translation_array(transfer_table* &table, - float out_x1, - float out_x2, - float in_x1, - float in_x2, - int in_total, - int out_total, - int &out_x1_int, - int &out_x2_int); - void translate(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, - int mode, - int row1, - int row2); - - OverlayFrame *overlay; - BlendEngine *blend_engine; -}; - -class BlendEngine : public LoadServer -{ -public: - BlendEngine(OverlayFrame *overlay, int cpus); - ~BlendEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; - - -// Arguments - VFrame *output; - VFrame *input; - float alpha; - int mode; -}; - - - - - - - - - - - - - -class OverlayFrame -{ -public: - OverlayFrame(int cpus = 1); - virtual ~OverlayFrame(); - -// Alpha is from 0 - 1 - int overlay(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, - int mode, - int interpolation_type); - - int overlay(VFrame *output, unsigned char *input, - float in_x1, float in_y1, float in_x2, float in_y2, - float out_x1, float out_y1, float out_x2, float out_y2, - int alpha, int in_w, int in_h); - int use_alpha, use_float, mode, interpolate; - int color_model; - - BlendEngine *blend_engine; - ScaleEngine *scale_engine; - TranslateEngine *translate_engine; - ScaleTranslateEngine *scaletranslate_engine; - - - VFrame *temp_frame; - int cpus; - -// TODO: These should all be in their respective Engine -// Global parameters for scaling units - VFrame *scale_output; - VFrame *scale_input; - float w_scale; - float h_scale; - int in_x1_int; - int in_y1_int; - int out_w_int; - int out_h_int; - int interpolation_type; -// Global parameters for translate units - VFrame *translate_output; - VFrame *translate_input; - float translate_in_x1; - float translate_in_y1; - float translate_in_x2; - float translate_in_y2; - float translate_out_x1; - float translate_out_y1; - float translate_out_x2; - float translate_out_y2; - float translate_alpha; - int translate_mode; -}; - -#endif diff --git a/cinelerra-5.1/cinelerra/overlayframe.h.floattable b/cinelerra-5.1/cinelerra/overlayframe.h.floattable deleted file mode 100644 index cf5b075c..00000000 --- a/cinelerra-5.1/cinelerra/overlayframe.h.floattable +++ /dev/null @@ -1,376 +0,0 @@ -#ifndef OVERLAYFRAME_H -#define OVERLAYFRAME_H - -#include "loadbalance.h" -#include "overlayframe.inc" -#include "vframe.inc" - - -// Issues encoutered with overlay - -// Floating point vs. int. On alpha the floating point interpolation is about -// 2x faster than integer interpolation. Integer interpolation uses 32 -// siginificant bits while floating point uses 24, however. - -// Single step vs. two step process. - -// A single step process would require performing blend with the output -// of BILINEAR or BICUBIC and trimming the output to fractional pixels. -// This is easy. - -// However reading the input for -// BILINEAR and BICUBIC would require trimming the input to fractional -// pixels often repeatedly since the interpolation reads the same pixels more -// than once. This is hard. - -// In the two step process one step worries purely about scaling, ignoring -// trimming at the input and output so redundant trimming is not done here. - -// The translation engine focuses purely on trimming input pixels and -// blending with the output - -// Translation - -typedef struct -{ - int in_x1; - float in_fraction1; - int in_x2; // Might be same as in_x1 for boundary - float in_fraction2; - float output_fraction; -} transfer_table; - - -class ScaleEngine; - -class ScalePackage : public LoadPackage -{ -public: - ScalePackage(); - - int out_row1, out_row2; -}; - -class ScaleUnit : public LoadClient -{ -public: - ScaleUnit(ScaleEngine *server, OverlayFrame *overlay); - ~ScaleUnit(); - - float cubic_bspline(float x); - void tabulate_bspline(float* &table, - float scale, - int pixels, - float coefficient); - void tabulate_blinear(int* &table_int, - float* &table_frac, - float* &table_antifrac, - float scale, - int pixel1, - int pixel2, - int total_pixels); - - void process_package(LoadPackage *package); - - OverlayFrame *overlay; - ScaleEngine *engine; -}; - -class ScaleEngine : public LoadServer -{ -public: - ScaleEngine(OverlayFrame *overlay, int cpus); - ~ScaleEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; -// Global parameters for scaling units - VFrame *scale_output; - VFrame *scale_input; - float w_scale; - float h_scale; - int in_x1_int; - int in_y1_int; - int out_w_int; - int out_h_int; - int interpolation_type; -}; - - - - - - - -class TranslateEngine; - -class TranslatePackage : public LoadPackage -{ -public: - TranslatePackage(); - - int out_row1, out_row2; -}; - - -class TranslateUnit : public LoadClient -{ -public: - TranslateUnit(TranslateEngine *server, OverlayFrame *overlay); - ~TranslateUnit(); - - void process_package(LoadPackage *package); - void translation_array(transfer_table* &table, - float out_x1, - float out_x2, - float in_x1, - float in_x2, - int in_total, - int out_total, - int &out_x1_int, - int &out_x2_int); - void translate(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, - int mode, - int row1, - int row2); - - OverlayFrame *overlay; - TranslateEngine *engine; -}; - -class TranslateEngine : public LoadServer -{ -public: - TranslateEngine(OverlayFrame *overlay, int cpus); - ~TranslateEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; -// Global parameters for translate units - VFrame *translate_output; - VFrame *translate_input; - float translate_in_x1; - float translate_in_y1; - float translate_in_x2; - float translate_in_y2; - float translate_out_x1; - float translate_out_y1; - float translate_out_x2; - float translate_out_y2; - float translate_alpha; - int translate_mode; -}; - - - - - - - - - -class ScaleTranslateEngine; - -class ScaleTranslatePackage : public LoadPackage -{ -public: - ScaleTranslatePackage(); - - int out_row1, out_row2; -}; - - -class ScaleTranslateUnit : public LoadClient -{ -public: - ScaleTranslateUnit(ScaleTranslateEngine *server, OverlayFrame *overlay); - ~ScaleTranslateUnit(); - - void process_package(LoadPackage *package); - void scale_array(int* &table, - int out_x1, - int out_x2, - int in_x1, - int in_x2, - int is_x); - - OverlayFrame *overlay; - ScaleTranslateEngine *scale_translate; -}; - -class ScaleTranslateEngine : public LoadServer -{ -public: - ScaleTranslateEngine(OverlayFrame *overlay, int cpus); - ~ScaleTranslateEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; - - -// Arguments - VFrame *output; - VFrame *input; - int in_x1; - int in_y1; - int in_x2; - int in_y2; - int out_x1; - int out_y1; - int out_x2; - int out_y2; - float alpha; - int mode; -}; - - - - - - - - - - - - - - - -class BlendEngine; - -class BlendPackage : public LoadPackage -{ -public: - BlendPackage(); - - int out_row1, out_row2; -}; - - -class BlendUnit : public LoadClient -{ -public: - BlendUnit(BlendEngine *server, OverlayFrame *overlay); - ~BlendUnit(); - - void process_package(LoadPackage *package); - void translation_array(transfer_table* &table, - float out_x1, - float out_x2, - float in_x1, - float in_x2, - int in_total, - int out_total, - int &out_x1_int, - int &out_x2_int); - void translate(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, - int mode, - int row1, - int row2); - - OverlayFrame *overlay; - BlendEngine *blend_engine; -}; - -class BlendEngine : public LoadServer -{ -public: - BlendEngine(OverlayFrame *overlay, int cpus); - ~BlendEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; - - -// Arguments - VFrame *output; - VFrame *input; - float alpha; - int mode; -}; - - - - - - - - - - - - - -class OverlayFrame -{ -public: - OverlayFrame(int cpus = 1); - virtual ~OverlayFrame(); - -// Alpha is from 0 - 1 - int overlay(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, - int mode, - int interpolation_type); - - int overlay(VFrame *output, unsigned char *input, - float in_x1, float in_y1, float in_x2, float in_y2, - float out_x1, float out_y1, float out_x2, float out_y2, - int alpha, int in_w, int in_h); - int use_alpha, use_float, mode, interpolate; - int color_model; - - BlendEngine *blend_engine; - ScaleEngine *scale_engine; - TranslateEngine *translate_engine; - ScaleTranslateEngine *scaletranslate_engine; - - - VFrame *temp_frame; - int cpus; - -}; - -#endif diff --git a/cinelerra-5.1/cinelerra/overlayframe.h.int b/cinelerra-5.1/cinelerra/overlayframe.h.int deleted file mode 100644 index a851140d..00000000 --- a/cinelerra-5.1/cinelerra/overlayframe.h.int +++ /dev/null @@ -1,352 +0,0 @@ -#ifndef OVERLAYFRAME_H -#define OVERLAYFRAME_H - -#include "loadbalance.h" -#include "overlayframe.inc" -#include "vframe.inc" - - - -// Translation - -typedef struct -{ - int in_x1; - float in_fraction1; - int in_x2; // Might be same as in_x1 for boundary - float in_fraction2; - float output_fraction; -} transfer_table; - - -class ScaleEngine; - -class ScalePackage : public LoadPackage -{ -public: - ScalePackage(); - - int out_row1, out_row2; -}; - - -class ScaleUnit : public LoadClient -{ -public: - ScaleUnit(ScaleEngine *server, OverlayFrame *overlay); - ~ScaleUnit(); - - int cubic_bspline(float x); - void tabulate_bspline(int* &table, - float scale, - int pixels, - float coefficient); - void tabulate_blinear(int* &table_int, - int* &table_frac, - float scale, - int pixel1, - int pixel2); - - void process_package(LoadPackage *package); - - OverlayFrame *overlay; -}; - -class ScaleEngine : public LoadServer -{ -public: - ScaleEngine(OverlayFrame *overlay, int cpus); - ~ScaleEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; -}; - - - - - - - -class TranslateEngine; - -class TranslatePackage : public LoadPackage -{ -public: - TranslatePackage(); - - int out_row1, out_row2; -}; - - -class TranslateUnit : public LoadClient -{ -public: - TranslateUnit(TranslateEngine *server, OverlayFrame *overlay); - ~TranslateUnit(); - - void process_package(LoadPackage *package); - void translation_array(transfer_table* &table, - float out_x1, - float out_x2, - float in_x1, - float in_x2, - int in_total, - int out_total, - int &out_x1_int, - int &out_x2_int); - void translate(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, - int mode, - int row1, - int row2); - - OverlayFrame *overlay; -}; - -class TranslateEngine : public LoadServer -{ -public: - TranslateEngine(OverlayFrame *overlay, int cpus); - ~TranslateEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; -}; - - - - - - - - - -class ScaleTranslateEngine; - -class ScaleTranslatePackage : public LoadPackage -{ -public: - ScaleTranslatePackage(); - - int out_row1, out_row2; -}; - - -class ScaleTranslateUnit : public LoadClient -{ -public: - ScaleTranslateUnit(ScaleTranslateEngine *server, OverlayFrame *overlay); - ~ScaleTranslateUnit(); - - void process_package(LoadPackage *package); - void scale_array(int* &table, - int out_x1, - int out_x2, - int in_x1, - int in_x2, - int is_x); - - OverlayFrame *overlay; - ScaleTranslateEngine *scale_translate; -}; - -class ScaleTranslateEngine : public LoadServer -{ -public: - ScaleTranslateEngine(OverlayFrame *overlay, int cpus); - ~ScaleTranslateEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; - - -// Arguments - VFrame *output; - VFrame *input; - int in_x1; - int in_y1; - int in_x2; - int in_y2; - int out_x1; - int out_y1; - int out_x2; - int out_y2; - float alpha; - int mode; -}; - - - - - - - - - - - - - - - -class BlendEngine; - -class BlendPackage : public LoadPackage -{ -public: - BlendPackage(); - - int out_row1, out_row2; -}; - - -class BlendUnit : public LoadClient -{ -public: - BlendUnit(BlendEngine *server, OverlayFrame *overlay); - ~BlendUnit(); - - void process_package(LoadPackage *package); - void translation_array(transfer_table* &table, - float out_x1, - float out_x2, - float in_x1, - float in_x2, - int in_total, - int out_total, - int &out_x1_int, - int &out_x2_int); - void translate(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, - int mode, - int row1, - int row2); - - OverlayFrame *overlay; - BlendEngine *blend_engine; -}; - -class BlendEngine : public LoadServer -{ -public: - BlendEngine(OverlayFrame *overlay, int cpus); - ~BlendEngine(); - - void init_packages(); - LoadClient* new_client(); - LoadPackage* new_package(); - - OverlayFrame *overlay; - - -// Arguments - VFrame *output; - VFrame *input; - float alpha; - int mode; -}; - - - - - - - - - - - - - -class OverlayFrame -{ -public: - OverlayFrame(int cpus = 1); - virtual ~OverlayFrame(); - -// Alpha is from 0 - 1 - int overlay(VFrame *output, - VFrame *input, - float in_x1, - float in_y1, - float in_x2, - float in_y2, - float out_x1, - float out_y1, - float out_x2, - float out_y2, - float alpha, - int mode, - int interpolation_type); - - int overlay(VFrame *output, unsigned char *input, - float in_x1, float in_y1, float in_x2, float in_y2, - float out_x1, float out_y1, float out_x2, float out_y2, - int alpha, int in_w, int in_h); - int use_alpha, use_float, mode, interpolate; - int color_model; - - BlendEngine *blend_engine; - ScaleEngine *scale_engine; - TranslateEngine *translate_engine; - ScaleTranslateEngine *scaletranslate_engine; - - - VFrame *temp_frame; - int cpus; - -// TODO: These should all be in their respective Engine -// Global parameters for scaling units - VFrame *scale_output; - VFrame *scale_input; - float w_scale; - float h_scale; - int in_x1_int; - int in_y1_int; - int out_w_int; - int out_h_int; - int interpolation_type; -// Global parameters for translate units - VFrame *translate_output; - VFrame *translate_input; - float translate_in_x1; - float translate_in_y1; - float translate_in_x2; - float translate_in_y2; - float translate_out_x1; - float translate_out_y1; - float translate_out_x2; - float translate_out_y2; - float translate_alpha; - int translate_mode; -}; - -#endif diff --git a/cinelerra-5.1/cinelerra/overlayframe.inc b/cinelerra-5.1/cinelerra/overlayframe.inc index f29bc572..18a926c9 100644 --- a/cinelerra-5.1/cinelerra/overlayframe.inc +++ b/cinelerra-5.1/cinelerra/overlayframe.inc @@ -24,84 +24,7 @@ // Modes -/* -source -x = porter duff operator -g = good guy -a = android -* = hv 4.6.1 - -cin 5.1 overlayframe TRANSFER_MODEs -x DST [Da, Dc] -x DST_ATOP [Sa, Sc * (1 - Da) + Dc * Sa] -x DST_IN [Da * Sa, Dc * Sa] -x DST_OUT [Da * (1 - Sa), Dc * (1 - Sa)] -x DST_OVER [Sa * (1 - Da) + Da, Sc * (1 - Da) + Dc] -x SRC [Sa, Sc] -x SRC_ATOP [Da, Sc * Da + Dc * (1 - Sa)] -x SRC_IN [Sa * Da, Sc * Da] -x SRC_OUT [Sa * (1 - Da), Sc * (1 - Da)] -x SRC_OVER [Sa + Da * (1 - Sa), Sc + (1 - Sa) * Dc] -g OR [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -a XOR [Sa * (1 - Da) + Da * (1 - Sa), Sc * (1 - Da) + Dc * (1 ­ Sa)] -* NORMAL [Sa + Da * (1 - Sa), Sc * Sa + Dc * (1 ­ Sa)]) -* ADDITION [(Sa + Da), (Sc + Dc)] -* SUBTRACT [(Sa - Da), (Sc ­ Dc)] -* MULTIPLY [(Sa * Da), Sc * Dc] -* DIVIDE [(Sa / Da), (Sc / Dc)] -* REPLACE [Sa, Sc] (fade = 1) -* MAX [max(Sa, Da), MAX(Sc, Dc)] -* MIN [min(Sa, Da), MIN(Sc, Dc)] -g AVERAGE [(Sa + Da) * 0.5, (Sc + Dc) * 0.5] -a DARKEN [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] -a LIGHTEN [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] - -https://developer.android.com/reference/android/graphics/PorterDuff.Mode.html - ADD Saturate(S + D) - CLEAR [0, 0] - DARKEN [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] - DST [Da, Dc] - DST_ATOP [Sa, Sa * Dc + Sc * (1 - Da)] - DST_IN [Sa * Da, Sa * Dc] - DST_OUT [Da * (1 - Sa), Dc * (1 - Sa)] - DST_OVER [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] - LIGHTEN [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] - MULTIPLY [Sa * Da, Sc * Dc] - OVERLAY (defined, but unspecified in android) - SCREEN [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] - SRC [Sa, Sc] - SRC_ATOP [Da, Sc * Da + (1 - Sa) * Dc] - SRC_IN [Sa * Da, Sc * Da] - SRC_OUT [Sa * (1 - Da), Sc * (1 - Da)] - SRC_OVER [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] - XOR [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] - -https://docs.gimp.org/2.6/en/gimp-concepts-layer-modes.html - Normal [M] - Dissolve [I + dots] - Multiply [M * I] - Divide [I / M] - Screen [1 - (1-M)*(1-I)] - Overlay [I * (I + 2*M*(1-I))] - Dodge [I / (1-M)] - Burn [1 - (1-I) / M] - Hard light [M>0.5 ? (1 - (1-2*(M-0.5))*(1 - I) : 2*M*I] - Soft light [((1-I)*M + Screen()) * I] - Grain extract [I - M + 0.5] - Grain merge [I + M - 0.5] - Difference [abs(I-M)] - Addition [min((I+M),1.0)] - Subtract [max((I-M),0.0)] - Darken only [min(M,I)] - Lighten only [max(M,I)] - Hue [hue(M) + sat(I)+val(I)] - Saturation [sat(M) + hue(I)+val(I)] - Color [hue(M)+sat(M) + val(I)] - Value [val(M) + sat(I)+hue(I)] - -*/ - -#define TRANSFER_TYPES 23 +#define TRANSFER_TYPES 30 #define TRANSFER_NORMAL 0 #define TRANSFER_ADDITION 1 @@ -111,21 +34,29 @@ https://docs.gimp.org/2.6/en/gimp-concepts-layer-modes.html #define TRANSFER_REPLACE 5 #define TRANSFER_MAX 6 #define TRANSFER_MIN 7 -#define TRANSFER_AVERAGE 8 -#define TRANSFER_DARKEN 9 -#define TRANSFER_LIGHTEN 10 -#define TRANSFER_DST 11 -#define TRANSFER_DST_ATOP 12 -#define TRANSFER_DST_IN 13 -#define TRANSFER_DST_OUT 14 -#define TRANSFER_DST_OVER 15 -#define TRANSFER_SRC 16 -#define TRANSFER_SRC_ATOP 17 -#define TRANSFER_SRC_IN 18 -#define TRANSFER_SRC_OUT 19 -#define TRANSFER_SRC_OVER 20 +#define TRANSFER_DARKEN 8 +#define TRANSFER_LIGHTEN 9 +#define TRANSFER_DST 10 +#define TRANSFER_DST_ATOP 11 +#define TRANSFER_DST_IN 12 +#define TRANSFER_DST_OUT 13 +#define TRANSFER_DST_OVER 14 +#define TRANSFER_SRC 15 +#define TRANSFER_SRC_ATOP 16 +#define TRANSFER_SRC_IN 17 +#define TRANSFER_SRC_OUT 18 +#define TRANSFER_SRC_OVER 19 +#define TRANSFER_AND 20 #define TRANSFER_OR 21 #define TRANSFER_XOR 22 +#define TRANSFER_OVERLAY 23 +#define TRANSFER_SCREEN 24 +#define TRANSFER_BURN 25 +#define TRANSFER_DODGE 26 +#define TRANSFER_HARDLIGHT 27 +#define TRANSFER_SOFTLIGHT 28 +#define TRANSFER_DIFFERENCE 29 + // Interpolation types diff --git a/cinelerra-5.1/cinelerra/overlaynearest.C b/cinelerra-5.1/cinelerra/overlaynearest.C new file mode 100644 index 00000000..e4a842d7 --- /dev/null +++ b/cinelerra-5.1/cinelerra/overlaynearest.C @@ -0,0 +1,195 @@ +#include "overlayframe.h" + +/* Nearest Neighbor scale / translate / blend ********************/ + +#define XBLEND_3NN(FN, temp_type, type, max, components, ofs, round) { \ + temp_type opcty = fade * max + round, trnsp = max - opcty; \ + type** output_rows = (type**)output->get_rows(); \ + type** input_rows = (type**)input->get_rows(); \ + ox *= components; \ + \ + for(int i = pkg->out_row1; i < pkg->out_row2; i++) { \ + int *lx = engine->in_lookup_x; \ + type* in_row = input_rows[*ly++]; \ + type* output = output_rows[i] + ox; \ + for(int j = 0; j < ow; j++) { \ + in_row += *lx++; \ + if( components == 4 ) { \ + temp_type r, g, b, a; \ + ALPHA4_BLEND(FN, temp_type, in_row, output, max, ofs, ofs, round); \ + ALPHA4_STORE(output, ofs, max); \ + } \ + else { \ + temp_type r, g, b; \ + ALPHA3_BLEND(FN, temp_type, in_row, output, max, ofs, ofs, round); \ + ALPHA3_STORE(output, ofs, max); \ + } \ + output += components; \ + } \ + } \ + break; \ +} + +#define XBLEND_NN(FN) { \ + switch(input->get_color_model()) { \ + case BC_RGB_FLOAT: XBLEND_3NN(FN, z_float, z_float, 1.f, 3, 0, 0.f); \ + case BC_RGBA_FLOAT: XBLEND_3NN(FN, z_float, z_float, 1.f, 4, 0, 0.f); \ + case BC_RGB888: XBLEND_3NN(FN, z_int32_t, z_uint8_t, 0xff, 3, 0, .5f); \ + case BC_YUV888: XBLEND_3NN(FN, z_int32_t, z_uint8_t, 0xff, 3, 0x80, .5f); \ + case BC_RGBA8888: XBLEND_3NN(FN, z_int32_t, z_uint8_t, 0xff, 4, 0, .5f); \ + case BC_YUVA8888: XBLEND_3NN(FN, z_int32_t, z_uint8_t, 0xff, 4, 0x80, .5f); \ + case BC_RGB161616: XBLEND_3NN(FN, z_int64_t, z_uint16_t, 0xffff, 3, 0, .5f); \ + case BC_YUV161616: XBLEND_3NN(FN, z_int64_t, z_uint16_t, 0xffff, 3, 0x8000, .5f); \ + case BC_RGBA16161616: XBLEND_3NN(FN, z_int64_t, z_uint16_t, 0xffff, 4, 0, .5f); \ + case BC_YUVA16161616: XBLEND_3NN(FN, z_int64_t, z_uint16_t, 0xffff, 4, 0x8000, .5f); \ + } \ + break; \ +} + +NNPackage::NNPackage() +{ +} + +NNUnit::NNUnit(NNEngine *server) + : LoadClient(server) +{ + this->engine = server; +} + +NNUnit::~NNUnit() +{ +} + +void NNUnit::process_package(LoadPackage *package) +{ + NNPackage *pkg = (NNPackage*)package; + VFrame *output = engine->output; + VFrame *input = engine->input; + int mode = engine->mode; + float fade = + BC_CModels::has_alpha(input->get_color_model()) && + mode == TRANSFER_REPLACE ? 1.f : engine->alpha; + + int ox = engine->out_x1i; + int ow = engine->out_x2i - ox; + int *ly = engine->in_lookup_y + pkg->out_row1; + + BLEND_SWITCH(XBLEND_NN); +} + +NNEngine::NNEngine(int cpus) + : LoadServer(cpus, cpus) +{ + in_lookup_x = 0; + in_lookup_y = 0; +} + +NNEngine::~NNEngine() +{ + if(in_lookup_x) + delete[] in_lookup_x; + if(in_lookup_y) + delete[] in_lookup_y; +} + +void NNEngine::init_packages() +{ + int in_w = input->get_w(); + int in_h = input->get_h(); + int out_w = output->get_w(); + int out_h = output->get_h(); + + float in_subw = in_x2 - in_x1; + float in_subh = in_y2 - in_y1; + float out_subw = out_x2 - out_x1; + float out_subh = out_y2 - out_y1; + int first, last, count, i; + int components = 3; + + out_x1i = rint(out_x1); + out_x2i = rint(out_x2); + if(out_x1i < 0) out_x1i = 0; + if(out_x1i > out_w) out_x1i = out_w; + if(out_x2i < 0) out_x2i = 0; + if(out_x2i > out_w) out_x2i = out_w; + int out_wi = out_x2i - out_x1i; + if( !out_wi ) return; + + delete[] in_lookup_x; + in_lookup_x = new int[out_wi]; + delete[] in_lookup_y; + in_lookup_y = new int[out_h]; + + switch(input->get_color_model()) { + case BC_RGBA_FLOAT: + case BC_RGBA8888: + case BC_YUVA8888: + case BC_RGBA16161616: + components = 4; + break; + } + + first = count = 0; + + for(i = out_x1i; i < out_x2i; i++) { + int in = (i - out_x1 + .5) * in_subw / out_subw + in_x1; + if(in < in_x1) + in = in_x1; + if(in > in_x2) + in = in_x2; + + if(in >= 0 && in < in_w && in >= in_x1 && i >= 0 && i < out_w) { + if(count == 0) { + first = i; + in_lookup_x[0] = in * components; + } + else { + in_lookup_x[count] = (in-last)*components; + } + last = in; + count++; + } + else if(count) + break; + } + out_x1i = first; + out_x2i = first + count; + first = count = 0; + + for(i = out_y1; i < out_y2; i++) { + int in = (i - out_y1+.5) * in_subh / out_subh + in_y1; + if(in < in_y1) in = in_y1; + if(in > in_y2) in = in_y2; + if(in >= 0 && in < in_h && i >= 0 && i < out_h) { + if(count == 0) first = i; + in_lookup_y[i] = in; + count++; + } + else if(count) + break; + } + out_y1 = first; + out_y2 = first + count; + + int rows = count; + int pkgs = get_total_packages(); + int row1 = out_y1, row2 = row1; + for(int i = 0; i < pkgs; row1=row2 ) { + NNPackage *package = (NNPackage*)get_package(i); + row2 = ++i * rows / pkgs + out_y1; + package->out_row1 = row1; + package->out_row2 = row2; + } +} + +LoadClient* NNEngine::new_client() +{ + return new NNUnit(this); +} + +LoadPackage* NNEngine::new_package() +{ + return new NNPackage; +} + + diff --git a/cinelerra-5.1/cinelerra/overlaysample.C b/cinelerra-5.1/cinelerra/overlaysample.C new file mode 100644 index 00000000..49071595 --- /dev/null +++ b/cinelerra-5.1/cinelerra/overlaysample.C @@ -0,0 +1,288 @@ +#include "overlayframe.h" + +/* Fully resampled scale / translate / blend ******************************/ +/* resample into a temporary row vector, then blend */ + +#define XSAMPLE(FN, temp_type, type, max, components, ofs, round) { \ + float temp[oh*components]; \ + temp_type opcty = fade * max + round, trnsp = max - opcty; \ + type **output_rows = (type**)voutput->get_rows() + o1i; \ + type **input_rows = (type**)vinput->get_rows(); \ + \ + for(int i = pkg->out_col1; i < pkg->out_col2; i++) { \ + type *input = input_rows[i - engine->col_out1 + engine->row_in]; \ + float *tempp = temp; \ + if( !k ) { /* direct copy case */ \ + type *ip = input + i1i * components; \ + for(int j = 0; j < oh; j++) { \ + *tempp++ = *ip++; \ + *tempp++ = *ip++ - ofs; \ + *tempp++ = *ip++ - ofs; \ + if( components == 4 ) *tempp++ = *ip++; \ + } \ + } \ + else { /* resample */ \ + for(int j = 0; j < oh; j++) { \ + float racc=0.f, gacc=0.f, bacc=0.f, aacc=0.f; \ + int ki = lookup_sk[j], x = lookup_sx0[j]; \ + type *ip = input + x * components; \ + float wacc = 0, awacc = 0; \ + while(x++ < lookup_sx1[j]) { \ + float kv = k[abs(ki >> INDEX_FRACTION)]; \ + /* handle fractional pixels on edges of input */ \ + if(x == i1i) kv *= i1f; \ + if(x + 1 == i2i) kv *= i2f; \ + if( components == 4 ) { awacc += kv; kv *= ip[3]; } \ + wacc += kv; \ + racc += kv * *ip++; \ + gacc += kv * (*ip++ - ofs); \ + bacc += kv * (*ip++ - ofs); \ + if( components == 4 ) { aacc += kv; ++ip; } \ + ki += kd; \ + } \ + if(wacc > 0.) wacc = 1. / wacc; \ + *tempp++ = racc * wacc; \ + *tempp++ = gacc * wacc; \ + *tempp++ = bacc * wacc; \ + if( components == 4 ) { \ + if(awacc > 0.) awacc = 1. / awacc; \ + *tempp++ = aacc * awacc; \ + } \ + } \ + } \ + \ + /* handle fractional pixels on edges of output */ \ + temp[0] *= o1f; temp[1] *= o1f; temp[2] *= o1f; \ + if( components == 4 ) temp[3] *= o1f; \ + tempp = temp + (oh-1)*components; \ + tempp[0] *= o2f; tempp[1] *= o2f; tempp[2] *= o2f; \ + if( components == 4 ) tempp[3] *= o2f; \ + tempp = temp; \ + /* blend output */ \ + for(int j = 0; j < oh; j++) { \ + type *output = output_rows[j] + i * components; \ + if( components == 4 ) { \ + temp_type r, g, b, a; \ + ALPHA4_BLEND(FN, temp_type, tempp, output, max, 0, ofs, round); \ + ALPHA4_STORE(output, ofs, max); \ + } \ + else { \ + temp_type r, g, b; \ + ALPHA3_BLEND(FN, temp_type, tempp, output, max, 0, ofs, round); \ + ALPHA3_STORE(output, ofs, max); \ + } \ + tempp += components; \ + } \ + } \ + break; \ +} + +#define XBLEND_SAMPLE(FN) { \ + switch(vinput->get_color_model()) { \ + case BC_RGB_FLOAT: XSAMPLE(FN, z_float, z_float, 1.f, 3, 0.f, 0.f); \ + case BC_RGBA_FLOAT: XSAMPLE(FN, z_float, z_float, 1.f, 4, 0.f, 0.f); \ + case BC_RGB888: XSAMPLE(FN, z_int32_t, z_uint8_t, 0xff, 3, 0, .5f); \ + case BC_YUV888: XSAMPLE(FN, z_int32_t, z_uint8_t, 0xff, 3, 0x80, .5f); \ + case BC_RGBA8888: XSAMPLE(FN, z_int32_t, z_uint8_t, 0xff, 4, 0, .5f); \ + case BC_YUVA8888: XSAMPLE(FN, z_int32_t, z_uint8_t, 0xff, 4, 0x80, .5f); \ + case BC_RGB161616: XSAMPLE(FN, z_int64_t, z_uint16_t, 0xffff, 3, 0, .5f); \ + case BC_YUV161616: XSAMPLE(FN, z_int64_t, z_uint16_t, 0xffff, 3, 0x8000, .5f); \ + case BC_RGBA16161616: XSAMPLE(FN, z_int64_t, z_uint16_t, 0xffff, 4, 0, .5f); \ + case BC_YUVA16161616: XSAMPLE(FN, z_int64_t, z_uint16_t, 0xffff, 4, 0x8000, .5f); \ + } \ + break; \ +} + + +SamplePackage::SamplePackage() +{ +} + +SampleUnit::SampleUnit(SampleEngine *server) + : LoadClient(server) +{ + this->engine = server; +} + +SampleUnit::~SampleUnit() +{ +} + +void SampleUnit::process_package(LoadPackage *package) +{ + SamplePackage *pkg = (SamplePackage*)package; + + float i1 = engine->in1; + float i2 = engine->in2; + float o1 = engine->out1; + float o2 = engine->out2; + + if(i2 - i1 <= 0 || o2 - o1 <= 0) + return; + + VFrame *voutput = engine->output; + VFrame *vinput = engine->input; + int mode = engine->mode; + float fade = + BC_CModels::has_alpha(vinput->get_color_model()) && + mode == TRANSFER_REPLACE ? 1.f : engine->alpha; + + //int iw = vinput->get_w(); + int i1i = floor(i1); + int i2i = ceil(i2); + float i1f = 1.f - i1 + i1i; + float i2f = 1.f - i2i + i2; + + int o1i = floor(o1); + int o2i = ceil(o2); + float o1f = 1.f - o1 + o1i; + float o2f = 1.f - o2i + o2; + int oh = o2i - o1i; + + float *k = engine->kernel->lookup; + //float kw = engine->kernel->width; + //int kn = engine->kernel->n; + int kd = engine->kd; + + int *lookup_sx0 = engine->lookup_sx0; + int *lookup_sx1 = engine->lookup_sx1; + int *lookup_sk = engine->lookup_sk; + //float *lookup_wacc = engine->lookup_wacc; + + BLEND_SWITCH(XBLEND_SAMPLE); +} + + +SampleEngine::SampleEngine(int cpus) + : LoadServer(cpus, cpus) +{ + lookup_sx0 = 0; + lookup_sx1 = 0; + lookup_sk = 0; + lookup_wacc = 0; + kd = 0; +} + +SampleEngine::~SampleEngine() +{ + if(lookup_sx0) delete [] lookup_sx0; + if(lookup_sx1) delete [] lookup_sx1; + if(lookup_sk) delete [] lookup_sk; + if(lookup_wacc) delete [] lookup_wacc; +} + +/* + * unlike the Direct and NN engines, the Sample engine works across + * output columns (it makes for more economical memory addressing + * during convolution) + */ +void SampleEngine::init_packages() +{ + int iw = input->get_w(); + int i1i = floor(in1); + int i2i = ceil(in2); + float i1f = 1.f - in1 + i1i; + float i2f = 1.f - i2i + in2; + + int oy = floor(out1); + float oyf = out1 - oy; + int oh = ceil(out2) - oy; + + float *k = kernel->lookup; + float kw = kernel->width; + int kn = kernel->n; + + if(in2 - in1 <= 0 || out2 - out1 <= 0) + return; + + /* determine kernel spatial coverage */ + float scale = (out2 - out1) / (in2 - in1); + float iscale = (in2 - in1) / (out2 - out1); + float coverage = fabs(1.f / scale); + float bound = (coverage < 1.f ? kw : kw * coverage) - (.5f / TRANSFORM_SPP); + float coeff = (coverage < 1.f ? 1.f : scale) * TRANSFORM_SPP; + + delete [] lookup_sx0; + delete [] lookup_sx1; + delete [] lookup_sk; + delete [] lookup_wacc; + + lookup_sx0 = new int[oh]; + lookup_sx1 = new int[oh]; + lookup_sk = new int[oh]; + lookup_wacc = new float[oh]; + + kd = (double)coeff * (1 << INDEX_FRACTION) + .5; + + /* precompute kernel values and weight sums */ + for(int i = 0; i < oh; i++) { + /* map destination back to source */ + double sx = (i - oyf + .5) * iscale + in1 - .5; + + /* + * clip iteration to source area but not source plane. Points + * outside the source plane count as transparent. Points outside + * the source area don't count at all. The actual convolution + * later will be clipped to both, but we need to compute + * weights. + */ + int sx0 = mmax((int)floor(sx - bound) + 1, i1i); + int sx1 = mmin((int)ceil(sx + bound), i2i); + int ki = (double)(sx0 - sx) * coeff * (1 << INDEX_FRACTION) + + (1 << (INDEX_FRACTION - 1)) + .5; + float wacc=0.; + + lookup_sx0[i] = -1; + lookup_sx1[i] = -1; + + for(int j= sx0; j < sx1; j++) { + int kv = (ki >> INDEX_FRACTION); + if(kv > kn) break; + if(kv >= -kn) { + /* + * the contribution of the first and last input pixel (if + * fractional) are linearly weighted by the fraction + */ + if(j == i1i) + wacc += k[abs(kv)] * i1f; + else if(j + 1 == i2i) + wacc += k[abs(kv)] * i2f; + else + wacc += k[abs(kv)]; + + /* this is where we clip the kernel convolution to the source plane */ + if(j >= 0 && j < iw) { + if(lookup_sx0[i] == -1) { + lookup_sx0[i] = j; + lookup_sk[i] = ki; + } + lookup_sx1[i] = j + 1; + } + } + ki += kd; + } + lookup_wacc[i] = wacc > 0. ? 1. / wacc : 0.; + } + + int cols = col_out2 - col_out1; + int pkgs = get_total_packages(); + int col1 = col_out1, col2 = col1; + for(int i = 0; i < pkgs; col1=col2 ) { + SamplePackage *package = (SamplePackage*)get_package(i); + col2 = ++i * cols / pkgs + col_out1; + package->out_col1 = col1; + package->out_col2 = col2; + } +} + +LoadClient* SampleEngine::new_client() +{ + return new SampleUnit(this); +} + +LoadPackage* SampleEngine::new_package() +{ + return new SamplePackage; +} + + diff --git a/cinelerra-5.1/cinelerra/patchbay.C b/cinelerra-5.1/cinelerra/patchbay.C index cb6c0c64..3292eeb5 100644 --- a/cinelerra-5.1/cinelerra/patchbay.C +++ b/cinelerra-5.1/cinelerra/patchbay.C @@ -192,7 +192,6 @@ void PatchBay::create_objects() "mode_replace", "mode_max", "mode_min", - "mode_average", "mode_darken", "mode_lighten", "mode_dst", @@ -205,8 +204,16 @@ void PatchBay::create_objects() "mode_srcin", "mode_srcout", "mode_srcover", + "mode_and", "mode_or", "mode_xor", + "mode_overlay", + "mode_screen", + "mode_burn", + "mode_dodge", + "mode_hardlight", + "mode_softlight", + "mode_difference", }; for( int mode=0; mode #include +#define QQ(q)#q +#define SS(s)QQ(s) // Shaders @@ -144,8 +147,51 @@ static const char *rgba_to_rgb_flatten = " gl_FragColor.a = 1.0;\n" "}\n"; +#define GL_STD_BLEND(FN) \ +static const char *blend_##FN##_frag = \ + "uniform sampler2D tex2;\n" \ + "uniform vec2 tex2_dimensions;\n" \ + "uniform float alpha;\n" \ + "void main() {\n" \ + " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" \ + " vec4 result;\n" \ + " result.rgb = "SS(COLOR_##FN(1.0, gl_FragColor.rgb, gl_FragColor.a, canvas.rgb, canvas.a))";\n" \ + " result.a = "SS(ALPHA_##FN(1.0, gl_FragColor.a, canvas.a))";\n" \ + " gl_FragColor = mix(canvas, result, alpha);\n" \ + "}\n" + +#define GL_VEC_BLEND(FN) \ +static const char *blend_##FN##_frag = \ + "uniform sampler2D tex2;\n" \ + "uniform vec2 tex2_dimensions;\n" \ + "uniform float alpha;\n" \ + "void main() {\n" \ + " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" \ + " vec4 result;\n" \ + " result.r = "SS(COLOR_##FN(1.0, gl_FragColor.r, gl_FragColor.a, canvas.r, canvas.a))";\n" \ + " result.g = "SS(COLOR_##FN(1.0, gl_FragColor.g, gl_FragColor.a, canvas.g, canvas.a))";\n" \ + " result.b = "SS(COLOR_##FN(1.0, gl_FragColor.b, gl_FragColor.a, canvas.b, canvas.a))";\n" \ + " result.a = "SS(ALPHA_##FN(1.0, gl_FragColor.a, canvas.a))";\n" \ + " result = clamp(result, 0.0, 1.0);\n" \ + " gl_FragColor = mix(canvas, result, alpha);\n" \ + "}\n" + +#undef mabs +#define mabs abs +#undef mmin +#define mmin min +#undef mmax +#define mmax max + +#undef ZERO +#define ZERO 0.0 +#undef ONE +#define ONE 1.0 +#undef TWO +#define TWO 2.0 + // NORMAL -static const char *blend_normal_frag = +static const char *blend_NORMAL_frag = "uniform sampler2D tex2;\n" "uniform vec2 tex2_dimensions;\n" "uniform float alpha;\n" @@ -155,264 +201,60 @@ static const char *blend_normal_frag = " gl_FragColor = mix(canvas, result, alpha);\n" "}\n"; -// ADDITION -static const char *blend_add_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = canvas + gl_FragColor;\n" - " result = clamp(result, 0.0, 1.0);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// SUBTRACT -static const char *blend_subtract_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = gl_FragColor - canvas;\n" - " result = clamp(result, 0.0, 1.0);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// MULTIPLY -static const char *blend_multiply_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = canvas * gl_FragColor;\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// DIVIDE -static const char *blend_divide_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = gl_FragColor / canvas;\n" - " if(canvas.r == 0.) result.r = 1.0;\n" - " if(canvas.g == 0.) result.g = 1.0;\n" - " if(canvas.b == 0.) result.b = 1.0;\n" - " if(canvas.a == 0.) result.a = 1.0;\n" - " result = clamp(result, 0.0, 1.0);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - // REPLACE -static const char *blend_replace_frag = - "uniform float alpha;\n" - "void main() {\n" - "}\n"; - -// MAX -static const char *blend_max_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = max(canvas, gl_FragColor);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// MIN -static const char *blend_min_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = min(canvas, gl_FragColor);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// AVERAGE -static const char *blend_average_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = (canvas + gl_FragColor) * 0.5;\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// DARKEN -static const char *blend_darken_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = vec4(canvas.rgb * (1.0 - gl_FragColor.a) +" - " gl_FragColor.rgb * (1.0 - canvas.a) +" - " min(canvas.rgb, gl_FragColor.rgb), " - " canvas.a + gl_FragColor.a - canvas.a * gl_FragColor.a);\n" - " result = clamp(result, 0.0, 1.0);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// LIGHTEN -static const char *blend_lighten_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = vec4(canvas.rgb * (1.0 - gl_FragColor.a) +" - " gl_FragColor.rgb * (1.0 - canvas.a) +" - " max(canvas.rgb, gl_FragColor.rgb), " - " canvas.a + gl_FragColor.a - canvas.a * gl_FragColor.a);\n" - " result = clamp(result, 0.0, 1.0);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// DST -static const char *blend_dst_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" -// " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" -// " vec4 result = canvas;\n" -// " gl_FragColor = mix(result, canvas, alpha);\n" - " gl_FragColor = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - "}\n"; - -// DST_ATOP -static const char *blend_dst_atop_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" +static const char *blend_REPLACE_frag = "uniform float alpha;\n" "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = vec4(canvas.rgb * gl_FragColor.a + " - "(1.0 - canvas.a) * gl_FragColor.rgb, gl_FragColor.a);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// DST_IN -static const char *blend_dst_in_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = canvas * gl_FragColor.a;\n" - " gl_FragColor = mix(canvas, result, alpha);\n" "}\n"; -// DST_OUT -static const char *blend_dst_out_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = canvas * (1.0 - gl_FragColor.a);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// DST_OVER -static const char *blend_dst_over_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = vec4(canvas.rgb + (1.0 - canvas.a) * gl_FragColor.rgb, " - " gl_FragColor.a + canvas.a - gl_FragColor.a * canvas.a);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// SRC -static const char *blend_src_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = gl_FragColor;\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// SRC_ATOP -static const char *blend_src_atop_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = vec4(gl_FragColor.rgb * canvas.a + " - "canvas.rgb * (1.0 - gl_FragColor.a), canvas.a);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// SRC_IN -static const char *blend_src_in_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = gl_FragColor * canvas.a;\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// SRC_OUT -static const char *blend_src_out_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = gl_FragColor * (1.0 - canvas.a);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; - -// SRC_OVER -static const char *blend_src_over_frag = +// ADDITION +static const char *blend_ADDITION_frag = "uniform sampler2D tex2;\n" "uniform vec2 tex2_dimensions;\n" "uniform float alpha;\n" "void main() {\n" " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = vec4(gl_FragColor.rgb + (1.0 - gl_FragColor.a) * canvas.rgb, " - "gl_FragColor.a + canvas.a - gl_FragColor.a * canvas.a);\n" + " vec4 result = clamp(gl_FragColor + canvas, 0.0, 1.0);\n" " gl_FragColor = mix(canvas, result, alpha);\n" "}\n"; -// OR -static const char *blend_or_frag = +// SUBTRACT +static const char *blend_SUBTRACT_frag = "uniform sampler2D tex2;\n" "uniform vec2 tex2_dimensions;\n" "uniform float alpha;\n" "void main() {\n" " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = canvas + gl_FragColor - canvas * gl_FragColor;\n" + " vec4 result = clamp(gl_FragColor - canvas, 0.0, 1.0);\n" " gl_FragColor = mix(canvas, result, alpha);\n" "}\n"; -// XOR -static const char *blend_xor_frag = - "uniform sampler2D tex2;\n" - "uniform vec2 tex2_dimensions;\n" - "uniform float alpha;\n" - "void main() {\n" - " vec4 canvas = texture2D(tex2, gl_FragCoord.xy / tex2_dimensions);\n" - " vec4 result = vec4(gl_FragColor.rgb * (1.0 - canvas.a) + " - "(1.0 - gl_FragColor.a) * canvas.rgb, " - "gl_FragColor.a + canvas.a - 2.0 * gl_FragColor.a * canvas.a);\n" - " gl_FragColor = mix(canvas, result, alpha);\n" - "}\n"; +GL_STD_BLEND(MULTIPLY); +GL_VEC_BLEND(DIVIDE); +GL_VEC_BLEND(MAX); +GL_VEC_BLEND(MIN); +GL_VEC_BLEND(DARKEN); +GL_VEC_BLEND(LIGHTEN); +GL_STD_BLEND(DST); +GL_STD_BLEND(DST_ATOP); +GL_STD_BLEND(DST_IN); +GL_STD_BLEND(DST_OUT); +GL_STD_BLEND(DST_OVER); +GL_STD_BLEND(SRC); +GL_STD_BLEND(SRC_ATOP); +GL_STD_BLEND(SRC_IN); +GL_STD_BLEND(SRC_OUT); +GL_STD_BLEND(SRC_OVER); +GL_STD_BLEND(AND); +GL_STD_BLEND(OR); +GL_STD_BLEND(XOR); +GL_VEC_BLEND(OVERLAY); +GL_STD_BLEND(SCREEN); +GL_VEC_BLEND(BURN); +GL_VEC_BLEND(DODGE); +GL_VEC_BLEND(HARDLIGHT); +GL_VEC_BLEND(SOFTLIGHT); +GL_VEC_BLEND(DIFFERENCE); static const char *read_texture_frag = "uniform sampler2D tex;\n" @@ -1082,29 +924,36 @@ void Playback3D::overlay_sync(Playback3DCommand *command) // To do these operations, we need to copy the input buffer to a texture // and blend 2 textures in a shader static const char * const overlay_shaders[TRANSFER_TYPES] = { - blend_normal_frag, // TRANSFER_NORMAL - blend_add_frag, // TRANSFER_ADDITION - blend_subtract_frag, // TRANSFER_SUBTRACT - blend_multiply_frag, // TRANSFER_MULTIPLY - blend_divide_frag, // TRANSFER_DIVIDE - blend_replace_frag, // TRANSFER_REPLACE - blend_max_frag, // TRANSFER_MAX - blend_min_frag, // TRANSFER_MIN - blend_average_frag, // TRANSFER_AVERAGE - blend_darken_frag, // TRANSFER_DARKEN - blend_lighten_frag, // TRANSFER_LIGHTEN - blend_dst_frag, // TRANSFER_DST - blend_dst_atop_frag, // TRANSFER_DST_ATOP - blend_dst_in_frag, // TRANSFER_DST_IN - blend_dst_out_frag, // TRANSFER_DST_OUT - blend_dst_over_frag, // TRANSFER_DST_OVER - blend_src_frag, // TRANSFER_SRC - blend_src_atop_frag, // TRANSFER_SRC_ATOP - blend_src_in_frag, // TRANSFER_SRC_IN - blend_src_out_frag, // TRANSFER_SRC_OUT - blend_src_over_frag, // TRANSFER_SRC_OVER - blend_or_frag, // TRANSFER_OR - blend_xor_frag // TRANSFER_XOR + blend_NORMAL_frag, // TRANSFER_NORMAL + blend_ADDITION_frag, // TRANSFER_ADDITION + blend_SUBTRACT_frag, // TRANSFER_SUBTRACT + blend_MULTIPLY_frag, // TRANSFER_MULTIPLY + blend_DIVIDE_frag, // TRANSFER_DIVIDE + blend_REPLACE_frag, // TRANSFER_REPLACE + blend_MAX_frag, // TRANSFER_MAX + blend_MIN_frag, // TRANSFER_MIN + blend_DARKEN_frag, // TRANSFER_DARKEN + blend_LIGHTEN_frag, // TRANSFER_LIGHTEN + blend_DST_frag, // TRANSFER_DST + blend_DST_ATOP_frag, // TRANSFER_DST_ATOP + blend_DST_IN_frag, // TRANSFER_DST_IN + blend_DST_OUT_frag, // TRANSFER_DST_OUT + blend_DST_OVER_frag, // TRANSFER_DST_OVER + blend_SRC_frag, // TRANSFER_SRC + blend_SRC_ATOP_frag, // TRANSFER_SRC_ATOP + blend_SRC_IN_frag, // TRANSFER_SRC_IN + blend_SRC_OUT_frag, // TRANSFER_SRC_OUT + blend_SRC_OVER_frag, // TRANSFER_SRC_OVER + blend_AND_frag, // TRANSFER_AND + blend_OR_frag, // TRANSFER_OR + blend_XOR_frag, // TRANSFER_XOR + blend_OVERLAY_frag, // TRANSFER_OVERLAY + blend_SCREEN_frag, // TRANSFER_SCREEN + blend_BURN_frag, // TRANSFER_BURN + blend_DODGE_frag, // TRANSFER_DODGE + blend_HARDLIGHT_frag, // TRANSFER_HARDLIGHT + blend_SOFTLIGHT_frag, // TRANSFER_SOFTLIGHT + blend_DIFFERENCE_frag, // TRANSFER_DIFFERENCE }; command->canvas->lock_canvas("Playback3D::overlay_sync"); diff --git a/cinelerra-5.1/cinelerra/preferencesthread.C b/cinelerra-5.1/cinelerra/preferencesthread.C index d02f9ad4..26c92c56 100644 --- a/cinelerra-5.1/cinelerra/preferencesthread.C +++ b/cinelerra-5.1/cinelerra/preferencesthread.C @@ -365,7 +365,7 @@ SET_TRACE PreferencesWindow::PreferencesWindow(MWindow *mwindow, PreferencesThread *thread, int x, int y, int w, int h) - : BC_Window(_(PROGRAM_NAME ": Preferences"), x,y, w,h, 1,0,1) + : BC_Window(_(PROGRAM_NAME ": Preferences"), x,y, w,h,w,h, 1) { this->mwindow = mwindow; this->thread = thread; diff --git a/cinelerra-5.1/cinelerra/theme.C b/cinelerra-5.1/cinelerra/theme.C index 6562a56c..827d5b9e 100644 --- a/cinelerra-5.1/cinelerra/theme.C +++ b/cinelerra-5.1/cinelerra/theme.C @@ -212,7 +212,6 @@ void Theme::initialize() new_image("mode_replace", "mode_replace.png"); new_image("mode_max", "mode_max.png"); new_image("mode_min", "mode_min.png"); - new_image("mode_average", "mode_average.png"); new_image("mode_darken", "mode_darken.png"); new_image("mode_lighten", "mode_lighten.png"); new_image("mode_dst", "mode_dst.png"); @@ -225,8 +224,16 @@ void Theme::initialize() new_image("mode_srcin", "mode_srcin.png"); new_image("mode_srcout", "mode_srcout.png"); new_image("mode_srcover", "mode_srcover.png"); + new_image("mode_and", "mode_and.png"); new_image("mode_or", "mode_or.png"); new_image("mode_xor", "mode_xor.png"); + new_image("mode_overlay", "mode_overlay.png"); + new_image("mode_screen", "mode_screen.png"); + new_image("mode_burn", "mode_burn.png"); + new_image("mode_dodge", "mode_dodge.png"); + new_image("mode_hardlight", "mode_hardlight.png"); + new_image("mode_softlight", "mode_softlight.png"); + new_image("mode_difference", "mode_difference.png"); new_image_set("mode_popup", 3, "mode_up.png", "mode_hi.png", "mode_dn.png"); diff --git a/cinelerra-5.1/cinelerra/vpatchgui.C b/cinelerra-5.1/cinelerra/vpatchgui.C index 94e194d5..1d4c46fb 100644 --- a/cinelerra-5.1/cinelerra/vpatchgui.C +++ b/cinelerra-5.1/cinelerra/vpatchgui.C @@ -332,8 +332,46 @@ int VModePatch::handle_event() void VModePatch::create_objects() { - for( int mode=0; modeadd_submenu(submenu = new VModePatchSubMenu(mode_item)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_ADDITION), TRANSFER_ADDITION)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SUBTRACT), TRANSFER_SUBTRACT)); + 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)); + 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)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DST_ATOP), TRANSFER_DST_ATOP)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DST_IN), TRANSFER_DST_IN)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DST_OUT), TRANSFER_DST_OUT)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DST_OVER), TRANSFER_DST_OVER)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SRC), TRANSFER_SRC)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SRC_ATOP), TRANSFER_SRC_ATOP)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SRC_IN), TRANSFER_SRC_IN)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SRC_OUT), TRANSFER_SRC_OUT)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SRC_OVER), TRANSFER_SRC_OVER)); + add_item(mode_item = new VModePatchItem(this, _("Logical..."), -1)); + mode_item->add_submenu(submenu = new VModePatchSubMenu(mode_item)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_MIN), TRANSFER_MIN)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_MAX), TRANSFER_MAX)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DARKEN), TRANSFER_DARKEN)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_LIGHTEN), TRANSFER_LIGHTEN)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_AND), TRANSFER_AND)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_OR), TRANSFER_OR)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_XOR), TRANSFER_XOR)); + add_item(mode_item = new VModePatchItem(this, _("graphic art..."), -1)); + mode_item->add_submenu(submenu = new VModePatchSubMenu(mode_item)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_OVERLAY), TRANSFER_OVERLAY)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SCREEN), TRANSFER_SCREEN)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_BURN), TRANSFER_BURN)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DODGE), TRANSFER_DODGE)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_DIFFERENCE),TRANSFER_DIFFERENCE)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_HARDLIGHT),TRANSFER_HARDLIGHT)); + submenu->add_submenuitem(new VModeSubMenuItem(submenu, mode_to_text(TRANSFER_SOFTLIGHT),TRANSFER_SOFTLIGHT)); } void VModePatch::update(int mode) @@ -343,6 +381,13 @@ void VModePatch::update(int mode) { VModePatchItem *item = (VModePatchItem*)get_item(i); item->set_checked(item->mode == mode); + VModePatchSubMenu *submenu = (VModePatchSubMenu *)item->get_submenu(); + if( !submenu ) continue; + int n = submenu->total_items(); + for( int j=0; jget_item(j); + subitem->set_checked(subitem->mode == mode); + } } } @@ -350,29 +395,36 @@ void VModePatch::update(int mode) const char* VModePatch::mode_to_text(int mode) { switch(mode) { - case TRANSFER_NORMAL: return _("Normal"); - case TRANSFER_ADDITION: return _("Addition"); - case TRANSFER_SUBTRACT: return _("Subtract"); - case TRANSFER_MULTIPLY: return _("Multiply"); - case TRANSFER_DIVIDE: return _("Divide"); - case TRANSFER_REPLACE: return _("Replace"); - case TRANSFER_MAX: return _("Max"); - case TRANSFER_MIN: return _("Min"); - case TRANSFER_AVERAGE: return _("Average"); - case TRANSFER_DARKEN: return _("Darken"); - case TRANSFER_LIGHTEN: return _("Lighten"); - case TRANSFER_DST: return _("Dst"); - case TRANSFER_DST_ATOP: return _("DstAtop"); - case TRANSFER_DST_IN: return _("DstIn"); - case TRANSFER_DST_OUT: return _("DstOut"); - case TRANSFER_DST_OVER: return _("DstOver"); - case TRANSFER_SRC: return _("Src"); - case TRANSFER_SRC_ATOP: return _("SrcAtop"); - case TRANSFER_SRC_IN: return _("SrcIn"); - case TRANSFER_SRC_OUT: return _("SrcOut"); - case TRANSFER_SRC_OVER: return _("SrcOver"); - case TRANSFER_OR: return _("Or"); - case TRANSFER_XOR: return _("Xor"); + case TRANSFER_NORMAL: return _("Normal"); + case TRANSFER_ADDITION: return _("Addition"); + case TRANSFER_SUBTRACT: return _("Subtract"); + case TRANSFER_MULTIPLY: return _("Multiply"); + case TRANSFER_DIVIDE: return _("Divide"); + case TRANSFER_REPLACE: return _("Replace"); + case TRANSFER_MAX: return _("Max"); + case TRANSFER_MIN: return _("Min"); + case TRANSFER_DARKEN: return _("Darken"); + case TRANSFER_LIGHTEN: return _("Lighten"); + case TRANSFER_DST: return _("Dst"); + case TRANSFER_DST_ATOP: return _("DstAtop"); + case TRANSFER_DST_IN: return _("DstIn"); + case TRANSFER_DST_OUT: return _("DstOut"); + case TRANSFER_DST_OVER: return _("DstOver"); + case TRANSFER_SRC: return _("Src"); + case TRANSFER_SRC_ATOP: return _("SrcAtop"); + case TRANSFER_SRC_IN: return _("SrcIn"); + case TRANSFER_SRC_OUT: return _("SrcOut"); + case TRANSFER_SRC_OVER: return _("SrcOver"); + case TRANSFER_AND: return _("And"); + case TRANSFER_OR: return _("Or"); + case TRANSFER_XOR: return _("Xor"); + case TRANSFER_OVERLAY: return _("Overlay"); + case TRANSFER_SCREEN: return _("Screen"); + case TRANSFER_BURN: return _("Burn"); + case TRANSFER_DODGE: return _("Dodge"); + case TRANSFER_HARDLIGHT: return _("Hardlight"); + case TRANSFER_SOFTLIGHT: return _("Softlight"); + case TRANSFER_DIFFERENCE: return _("Difference"); } return _("Normal"); } @@ -389,6 +441,37 @@ VModePatchItem::VModePatchItem(VModePatch *popup, const char *text, int mode) int VModePatchItem::handle_event() { + if( mode >= 0 ) { + popup->mode = mode; +// popup->set_icon(popup->patch->patchbay->mode_to_icon(mode)); + popup->handle_event(); + } + return 1; +} + +VModePatchSubMenu::VModePatchSubMenu(VModePatchItem *mode_item) +{ + this->mode_item = mode_item; +} +VModePatchSubMenu::~VModePatchSubMenu() +{ +} + +VModeSubMenuItem::VModeSubMenuItem(VModePatchSubMenu *submenu, const char *text, int mode) + : BC_MenuItem(text) +{ + this->submenu = submenu; + this->mode = mode; + VModePatch *popup = submenu->mode_item->popup; + if(this->mode == popup->mode) set_checked(1); +} +VModeSubMenuItem::~VModeSubMenuItem() +{ +} + +int VModeSubMenuItem::handle_event() +{ + VModePatch *popup = submenu->mode_item->popup; popup->mode = mode; // popup->set_icon(popup->patch->patchbay->mode_to_icon(mode)); popup->handle_event(); diff --git a/cinelerra-5.1/cinelerra/vpatchgui.h b/cinelerra-5.1/cinelerra/vpatchgui.h index e368c8ec..ff6b98d3 100644 --- a/cinelerra-5.1/cinelerra/vpatchgui.h +++ b/cinelerra-5.1/cinelerra/vpatchgui.h @@ -22,6 +22,8 @@ #ifndef VPATCHGUI_H #define VPATCHGUI_H +#include "bcmenuitem.h" +#include "bcmenupopup.h" #include "floatauto.inc" #include "guicast.h" #include "patchgui.h" @@ -108,6 +110,26 @@ public: int mode; }; +class VModePatchSubMenu : public BC_SubMenu +{ +public: + VModePatchSubMenu(VModePatchItem *mode_item); + ~VModePatchSubMenu(); + + VModePatchItem *mode_item; +}; + +class VModeSubMenuItem : public BC_MenuItem +{ +public: + VModeSubMenuItem(VModePatchSubMenu *submenu, const char *text, int mode); + ~VModeSubMenuItem(); + + int handle_event(); + VModePatchSubMenu *submenu; + int mode; +}; + class VKeyModePatch : public VModePatch { public: diff --git a/cinelerra-5.1/guicast/bcmenuitem.C b/cinelerra-5.1/guicast/bcmenuitem.C index 6279bc6f..86a1e005 100644 --- a/cinelerra-5.1/guicast/bcmenuitem.C +++ b/cinelerra-5.1/guicast/bcmenuitem.C @@ -130,6 +130,7 @@ int BC_MenuItem::deactivate_submenus(BC_MenuPopup *exclude) { submenu->deactivate_submenus(exclude); submenu->deactivate_menu(); + submenu->popup_menu = 0; highlighted = 0; } return 0; @@ -149,6 +150,7 @@ int BC_MenuItem::activate_submenu() &new_x, &new_y, &tempwin); + submenu->popup_menu = menu_popup->popup_menu; submenu->activate_menu(new_x + 5, new_y, menu_popup->w - 10, h, 0, 0); highlighted = 1; } @@ -430,6 +432,11 @@ int BC_MenuItem::add_submenu(BC_SubMenu *submenu) return 0; } +BC_SubMenu* BC_MenuItem::get_submenu() +{ + return submenu; +} + char* BC_MenuItem::get_text() { return text; diff --git a/cinelerra-5.1/guicast/bcmenuitem.h b/cinelerra-5.1/guicast/bcmenuitem.h index 58aaa1d3..5a2faf21 100644 --- a/cinelerra-5.1/guicast/bcmenuitem.h +++ b/cinelerra-5.1/guicast/bcmenuitem.h @@ -66,6 +66,7 @@ public: int draw(); BC_WindowBase* get_top_level(); BC_PopupMenu* get_popup_menu(); + BC_SubMenu *get_submenu(); private: BC_WindowBase *top_level; diff --git a/cinelerra-5.1/guicast/bcmenupopup.C b/cinelerra-5.1/guicast/bcmenupopup.C index 1888e6cf..9c679a3d 100644 --- a/cinelerra-5.1/guicast/bcmenupopup.C +++ b/cinelerra-5.1/guicast/bcmenupopup.C @@ -428,7 +428,13 @@ BC_Popup* BC_MenuPopup::get_popup() int BC_MenuPopup::cursor_inside() { - return !popup || !popup->cursor_above() ? 0 : 1; + if( !popup ) return 0; + if( popup->cursor_above() ) return 1; + for( int i=0; isubmenu ) continue; + if( menu_items[i]->submenu->cursor_inside() ) return 1; + } + return 0; } int BC_MenuPopup::get_w() diff --git a/cinelerra-5.1/guicast/bcwindowbase.C b/cinelerra-5.1/guicast/bcwindowbase.C index b97208fa..b6d54fe0 100644 --- a/cinelerra-5.1/guicast/bcwindowbase.C +++ b/cinelerra-5.1/guicast/bcwindowbase.C @@ -3761,9 +3761,11 @@ int BC_WindowBase::dump_windows() this, (void*)this->win, title, w,h,x,y, typeid(*this).name()); for(int i = 0; i < subwindows->size(); i++) subwindows->get(i)->dump_windows(); - for(int i = 0; i < popups.size(); i++) - printf("\tBC_WindowBase::dump_windows popup=%p win=%p\n", - popups.get(i), (void*)popups.get(i)->win); + for(int i = 0; i < popups.size(); i++) { + BC_WindowBase *p = popups[i]; + printf("\tBC_WindowBase::dump_windows popup=%p win=%p '%s', %dx%d+%d+%d %s\n", + p, (void*)p->win, p->title, p->w,p->h,p->x,p->y, typeid(*p).name()); + } return 0; } diff --git a/cinelerra-5.1/plugins/overlay/overlay.C b/cinelerra-5.1/plugins/overlay/overlay.C index e1ca0961..359867fd 100644 --- a/cinelerra-5.1/plugins/overlay/overlay.C +++ b/cinelerra-5.1/plugins/overlay/overlay.C @@ -29,6 +29,7 @@ #include "language.h" #include "overlayframe.h" #include "pluginvclient.h" +#include "vpatchgui.h" #include "vframe.h" #include @@ -149,33 +150,7 @@ OverlayConfig::OverlayConfig() const char* OverlayConfig::mode_to_text(int mode) { - switch(mode) { - case TRANSFER_NORMAL: return _("Normal"); - case TRANSFER_ADDITION: return _("Addition"); - case TRANSFER_SUBTRACT: return _("Subtract"); - case TRANSFER_MULTIPLY: return _("Multiply"); - case TRANSFER_DIVIDE: return _("Divide"); - case TRANSFER_REPLACE: return _("Replace"); - case TRANSFER_MAX: return _("Max"); - case TRANSFER_MIN: return _("Min"); - case TRANSFER_AVERAGE: return _("Average"); - case TRANSFER_DARKEN: return _("Darken"); - case TRANSFER_LIGHTEN: return _("Lighten"); - case TRANSFER_DST: return _("Dst"); - case TRANSFER_DST_ATOP: return _("DstAtop"); - case TRANSFER_DST_IN: return _("DstIn"); - case TRANSFER_DST_OUT: return _("DstOut"); - case TRANSFER_DST_OVER: return _("DstOver"); - case TRANSFER_SRC: return _("Src"); - case TRANSFER_SRC_ATOP: return _("SrcAtop"); - case TRANSFER_SRC_IN: return _("SrcIn"); - case TRANSFER_SRC_OUT: return _("SrcOut"); - case TRANSFER_SRC_OVER: return _("SrcOver"); - case TRANSFER_OR: return _("Or"); - case TRANSFER_XOR: return _("Xor"); - default: break; - } - return _("Normal"); + return VModePatch::mode_to_text(mode); } const char* OverlayConfig::direction_to_text(int direction) @@ -479,141 +454,109 @@ int Overlay::handle_opengl() " gl_FragColor = result;\n" "}\n"; - -// NORMAL -static const char *blend_normal_frag = +#define QQ(q)#q +#define SS(s)QQ(s) + +#define GL_STD_FRAG(FN) static const char *blend_##FN##_frag = \ + " vec4 result;\n" \ + " result.rgb = "SS(COLOR_##FN(1.0, src_color.rgb, src_color.a, dst_color.rgb, dst_color.a))";\n" \ + " result.a = "SS(ALPHA_##FN(1.0, src_color.a, dst_color.a))";\n" \ + +#define GL_VEC_FRAG(FN) static const char *blend_##FN##_frag = \ + " vec4 result;\n" \ + " result.r = "SS(COLOR_##FN(1.0, src_color.r, src_color.a, dst_color.r, dst_color.a))";\n" \ + " result.g = "SS(COLOR_##FN(1.0, src_color.g, src_color.a, dst_color.g, dst_color.a))";\n" \ + " result.b = "SS(COLOR_##FN(1.0, src_color.b, src_color.a, dst_color.b, dst_color.a))";\n" \ + " result.a = "SS(ALPHA_##FN(1.0, src_color.a, dst_color.a))";\n" \ + " result = clamp(result, 0.0, 1.0);\n" \ + +#undef mabs +#define mabs abs +#undef mmin +#define mmin min +#undef mmax +#define mmax max + +#undef ZERO +#define ZERO 0.0 +#undef ONE +#define ONE 1.0 +#undef TWO +#define TWO 2.0 + +static const char *blend_NORMAL_frag = " vec4 result = mix(src_color, src_color, src_color.a);\n"; -// ADDITION -static const char *blend_add_frag = +static const char *blend_ADDITION_frag = " vec4 result = dst_color + src_color;\n" " result = clamp(result, 0.0, 1.0);\n"; -// SUBTRACT -static const char *blend_subtract_frag = +static const char *blend_SUBTRACT_frag = " vec4 result = dst_color - src_color;\n" " result = clamp(result, 0.0, 1.0);\n"; -// MULTIPLY -static const char *blend_multiply_frag = - " vec4 result = dst_color * src_color;\n"; - -// DIVIDE -static const char *blend_divide_frag = - " vec4 result = dst_color / src_color;\n" - " if(src_color.r == 0.) result.r = 1.0;\n" - " if(src_color.g == 0.) result.g = 1.0;\n" - " if(src_color.b == 0.) result.b = 1.0;\n" - " if(src_color.a == 0.) result.a = 1.0;\n" - " result = clamp(result, 0.0, 1.0);\n"; - -// MAX -static const char *blend_max_frag = - " vec4 result = max(src_color, dst_color);\n"; - -// MIN -static const char *blend_min_frag = - " vec4 result = min(src_color, dst_color);\n"; - -// AVERAGE -static const char *blend_average_frag = - " vec4 result = (src_color + dst_color) * 0.5;\n"; - -// DARKEN -static const char *blend_darken_frag = - " vec4 result = vec4(src_color.rgb * (1.0 - dst_color.a) +" - " dst_color.rgb * (1.0 - src_color.a) +" - " min(src_color.rgb, dst_color.rgb), " - " src_color.a + dst_color.a - src_color.a * dst_color.a);\n" - " result = clamp(result, 0.0, 1.0);\n"; - -// LIGHTEN -static const char *blend_lighten_frag = - " vec4 result = vec4(src_color.rgb * (1.0 - dst_color.a) +" - " dst_color.rgb * (1.0 - src_color.a) +" - " max(src_color.rgb, dst_color.rgb), " - " src_color.a + dst_color.a - src_color.a * dst_color.a);\n" - " result = clamp(result, 0.0, 1.0);\n"; - -// DST -static const char *blend_dst_frag = - " vec4 result = dst_color;\n"; - -// DST_ATOP -static const char *blend_dst_atop_frag = - " vec4 result = vec4(src_color.rgb * dst_color.a + " - "(1.0 - src_color.a) * dst_color.rgb, dst_color.a);\n"; - -// DST_IN -static const char *blend_dst_in_frag = - " vec4 result = src_color * dst_color.a;\n"; - -// DST_OUT -static const char *blend_dst_out_frag = - " vec4 result = src_color * (1.0 - dst_color.a);\n"; - -// DST_OVER -static const char *blend_dst_over_frag = - " vec4 result = vec4(src_color.rgb + (1.0 - src_color.a) * dst_color.rgb, " - " dst_color.a + src_color.a - dst_color.a * src_color.a);\n"; - -// SRC -static const char *blend_src_frag = +static const char *blend_REPLACE_frag = " vec4 result = src_color;\n"; -// SRC_ATOP -static const char *blend_src_atop_frag = - " vec4 result = vec4(dst_color.rgb * src_color.a + " - "src_color.rgb * (1.0 - dst_color.a), src_color.a);\n"; - -// SRC_IN -static const char *blend_src_in_frag = - " vec4 result = dst_color * src_color.a;\n"; - -// SRC_OUT -static const char *blend_src_out_frag = - " vec4 result = dst_color * (1.0 - src_color.a);\n"; - -// SRC_OVER -static const char *blend_src_over_frag = - " vec4 result = vec4(dst_color.rgb + (1.0 - dst_color.a) * src_color.rgb, " - "dst_color.a + src_color.a - dst_color.a * src_color.a);\n"; - -// OR -static const char *blend_or_frag = - " vec4 result = src_color + dst_color - src_color * dst_color;\n"; - -// XOR -static const char *blend_xor_frag = - " vec4 result = vec4(dst_color.rgb * (1.0 - src_color.a) + " - "(1.0 - dst_color.a) * src_color.rgb, " - "dst_color.a + src_color.a - 2.0 * dst_color.a * src_color.a);\n"; +GL_STD_FRAG(MULTIPLY); +GL_VEC_FRAG(DIVIDE); +GL_VEC_FRAG(MAX); +GL_VEC_FRAG(MIN); +GL_VEC_FRAG(DARKEN); +GL_VEC_FRAG(LIGHTEN); +GL_STD_FRAG(DST); +GL_STD_FRAG(DST_ATOP); +GL_STD_FRAG(DST_IN); +GL_STD_FRAG(DST_OUT); +GL_STD_FRAG(DST_OVER); +GL_STD_FRAG(SRC); +GL_STD_FRAG(SRC_ATOP); +GL_STD_FRAG(SRC_IN); +GL_STD_FRAG(SRC_OUT); +GL_STD_FRAG(SRC_OVER); +GL_STD_FRAG(AND); +GL_STD_FRAG(OR); +GL_STD_FRAG(XOR); +GL_VEC_FRAG(OVERLAY); +GL_STD_FRAG(SCREEN); +GL_VEC_FRAG(BURN); +GL_VEC_FRAG(DODGE); +GL_VEC_FRAG(HARDLIGHT); +GL_VEC_FRAG(SOFTLIGHT); +GL_VEC_FRAG(DIFFERENCE); static const char * const overlay_shaders[TRANSFER_TYPES] = { - blend_normal_frag, // TRANSFER_NORMAL - blend_add_frag, // TRANSFER_ADDITION - blend_subtract_frag, // TRANSFER_SUBTRACT - blend_multiply_frag, // TRANSFER_MULTIPLY - blend_divide_frag, // TRANSFER_DIVIDE - blend_src_frag, // TRANSFER_REPLACE - blend_max_frag, // TRANSFER_MAX - blend_min_frag, // TRANSFER_MIN - blend_average_frag, // TRANSFER_AVERAGE - blend_darken_frag, // TRANSFER_DARKEN - blend_lighten_frag, // TRANSFER_LIGHTEN - blend_dst_frag, // TRANSFER_DST - blend_dst_atop_frag, // TRANSFER_DST_ATOP - blend_dst_in_frag, // TRANSFER_DST_IN - blend_dst_out_frag, // TRANSFER_DST_OUT - blend_dst_over_frag, // TRANSFER_DST_OVER - blend_src_frag, // TRANSFER_SRC - blend_src_atop_frag, // TRANSFER_SRC_ATOP - blend_src_in_frag, // TRANSFER_SRC_IN - blend_src_out_frag, // TRANSFER_SRC_OUT - blend_src_over_frag, // TRANSFER_SRC_OVER - blend_or_frag, // TRANSFER_OR - blend_xor_frag // TRANSFER_XOR - }; + blend_NORMAL_frag, // TRANSFER_NORMAL + blend_ADDITION_frag, // TRANSFER_ADDITION + blend_SUBTRACT_frag, // TRANSFER_SUBTRACT + blend_MULTIPLY_frag, // TRANSFER_MULTIPLY + blend_DIVIDE_frag, // TRANSFER_DIVIDE + blend_REPLACE_frag, // TRANSFER_REPLACE + blend_MAX_frag, // TRANSFER_MAX + blend_MIN_frag, // TRANSFER_MIN + blend_DARKEN_frag, // TRANSFER_DARKEN + blend_LIGHTEN_frag, // TRANSFER_LIGHTEN + blend_DST_frag, // TRANSFER_DST + blend_DST_ATOP_frag, // TRANSFER_DST_ATOP + blend_DST_IN_frag, // TRANSFER_DST_IN + blend_DST_OUT_frag, // TRANSFER_DST_OUT + blend_DST_OVER_frag, // TRANSFER_DST_OVER + blend_SRC_frag, // TRANSFER_SRC + blend_SRC_ATOP_frag, // TRANSFER_SRC_ATOP + blend_SRC_IN_frag, // TRANSFER_SRC_IN + blend_SRC_OUT_frag, // TRANSFER_SRC_OUT + blend_SRC_OVER_frag, // TRANSFER_SRC_OVER + blend_AND_frag, // TRANSFER_AND + blend_OR_frag, // TRANSFER_OR + blend_XOR_frag, // TRANSFER_XOR + blend_OVERLAY_frag, // TRANSFER_OVERLAY + blend_SCREEN_frag, // TRANSFER_SCREEN + blend_BURN_frag, // TRANSFER_BURN + blend_DODGE_frag, // TRANSFER_DODGE + blend_HARDLIGHT_frag, // TRANSFER_HARDLIGHT + blend_SOFTLIGHT_frag, // TRANSFER_SOFTLIGHT + blend_DIFFERENCE_frag, // TRANSFER_DIFFERENCE +}; glDisable(GL_BLEND); VFrame *dst = get_output(output_layer); diff --git a/cinelerra-5.1/plugins/theme_blond/data/mode_and.png b/cinelerra-5.1/plugins/theme_blond/data/mode_and.png new file mode 100644 index 0000000000000000000000000000000000000000..dbbc4e204819fd377226bfbf91ae3a1e993dba69 GIT binary patch literal 831 zcmV-F1Hk-=P)cpdsS-JWs6;QEI7S>eDQKtdHl6`?(WVi0Mn zHgQzDw&VBwc87zT62zrqPBYs5=sP<*GqSzC&Hu8UogH5k1z0T!A}@#df$1!JWH4@oo^rX@9(W#**v;_^;z9l#A*>z;Ng?x^Do~8yumB&NzKo}FaX3I z%lcP0s7F2U&8>yj`^S?8FrBCM zR{!RYfFT}nsKX3U07+1Xdei}Xv;Ib}_Um42Hh0mO74FXNnrVA9<@8z;Ucfli6BdLD zvy;*ukMiL-5iv7~CaTtLGkj{qfI76cEQ$g|cT#yYvE&>gYb&mmj^5swET5#pdzXfj z$!Mb|s5f&+b|&qhH9IliFipXA_{+j*s!zUq>l{yR& zrI{T~PYTqTdK0Ib+6(1aNf}CW&;O~4cKfHI+gXVbz)XG8yYsUmih5B6e+CYcXHLX{ z0|p1x>%HdgpoIxw*u6ogq&t4J58@?8^dC4xP_L)WT~_w^X?{3LMNPm=MQk;Xqp5j? zrN$X$P%qAVpLn12yRIrH7g~h?VyO$4UK@`mqc?i8Y(YC!_JBnY1wjDL=lW`UcI}=0 zU;gMF9M$srV(ZO8Q|AJRLjX16b2!Xri^-PHJ#j&Z!rhPF&wjW!oKBA~b`pt2r!l#9 zMTx=UWkk#2SeOGIVf3sx{O;?{MP~(zImHR(oPNPt3E)$*AxC$~YLeD(;5pcpg?#{c zf#0jO&%SRsSq>!sT?+Q^a89~N62NC!2E;})zVrfeW)7Tle*?#iOa)DDO56Yd002ov JPDHLkV1n-oc~}4d literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blond/data/mode_average.png b/cinelerra-5.1/plugins/theme_blond/data/mode_average.png deleted file mode 100644 index 3edf8524135218ed830e1d7e3ad5d75f7ac7a161..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 840 zcmV-O1GoH%P)!Xy9y0_90WK~y-6os>;zT}2efe`n_0 zkG!OLCQ*!7sbUeN_(8QGl}a}%rKw0PZkj^VMaZJkg>+#>kh&2!6+zKODK11^X#};4 zMg$dYp$OU#7o|<5U#Lmjm*(Z(_wJqJ;=Z(rK@iVkhT+Wb{Qtw585tfP=6}V=$cW~7 z4wgox$bZF(Qd)&8%TmpFWZm4Jr_VHt1Q@Kh27217frZ@9{FMTUhS-V&A8rKHpx)ga zeQRwq_rTVNt{)ydw~VrC`gC&e{jUarSncicb4gqZsK8?Go4HFg?A`X~#`_m=`VSI# zc2h%~eDPENrP;W#7-I%F=#1(a8=8Imf&Ajt^vhGX6{d&=^tfFR(K%8mjA2LZq- z#-r==shRZH$zE0Y`a}=N`ny}*H9-^+3}l&YE2VQhQJn63p|Ru18)cA*@7J{2?!k5W zo8z--;_=#1Ca$(SAOryca31k-{SHopeemPUo}e z)eri!mY7*la_DH^<*RXJs!|T7c1yWjYKVB8KXkNyayn7Z=#IrS=E|HNc(?CbGeUgT zKEvBe+koKo?B!(gRAOdh&u9B~=5LHQto^IX#VqWe$xiSc@PXUhlM3L0JIBUKay_V5MJI@-t40DHnb%SZ3(B(>U*EN z->*2tV3~4Pw5n9tDl(kK;-GGcM=M?B0F~Y;oPf~#hO}K zwt|IVW`+TR3GCg@@Kb^#P2|RfhL8b@aD6^+eEZ43ecp1ijC_$+Mk}Xi0ccE;5~U<5 zaTh3;ev!6qrg~LpioyNIYhF4gSAPn&a+wjgqX^I>Nq|u64y%}d3vcGZd;d2uj59pP SC9Kf^0000?P)C-d?OQJ&LUtxJ6-CT>J@MfGE zUA=YTt@FMgj%fXfn5i#zc;kSjAg%ygB)yp>=Bd}4-~fY1<{!k7>Vv9Kw86-Hc-*>)HQj1A?8rkPq<o-I8v`Ob$js)fBn*SYU5acef`p}b^gP`NO$Fj&;dNcdMjOi`f$%-XDL~SJ8zB`1tDMoKoqB3 zIr%W&azwJ=Tq6qMD90Q?N5C7bNoS6gX Z+)woy?36)5Dv|&I002ovPDHLkV1h8`Kc@fy literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blond/data/mode_difference.png b/cinelerra-5.1/plugins/theme_blond/data/mode_difference.png new file mode 100644 index 0000000000000000000000000000000000000000..c036b9d9555ef2e374470466b8e1aa5f33f69444 GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa&H|6fVg?3*gA5FU){JG5i7Y@t z_7YEDSM~>-(xQBt(_F4^0SayQba4#PIDdDNE!QCjf!6(Z*9dBRDn_$i(VOluG5U#s zr8nQk?GYEfbJCS>ED`8#a5>rEDwrhYxsv%Z&*#0B{A~aBAF=b?6Y*N|0i%$HZStSk zNjVJm*M8M#bg^YrKjX7$X*p_mIxl!#?&mw<4h2Q;y7fP1X)avH$iyn(HgSf?gJz!eHX6?-yk|@Ia^@>M)pTdT1e>U7$x{~FY@(xz5M4!)#=YM9Y Y{HHm)YU=)5K<6`fy85}Sb4q9e01l34$N&HU literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blond/data/mode_dodge.png b/cinelerra-5.1/plugins/theme_blond/data/mode_dodge.png new file mode 100644 index 0000000000000000000000000000000000000000..68eed2ac21d5b799266d9e8eb1b83e245b7a4d8a GIT binary patch literal 895 zcmV-_1AzRAP)5zIo-g&I-8 zDE5mMD{Wevq$=rTl1w^p-n;L(m~n!LAYLxqb2#UJ&;R@n9GRJ!;eVak*;yCIF=#IE zBLAA#h?6i1+HUHlks9y4Q)TZRH(q<{taYv(4%j@m)BzNCMJMOWaf9-qXh0Z`GhvGf?bZ)qE=>7_T2*#ocH~;&@bY;}Rp}NY2qA`;@q7HaD>-b43B-g=+6KTIY)&yoxO^!* zu)oo$3l^^!OPaB7FuAniKKddLD5g+yO=%r)VKomb0_f0ves#$vy>eUX>xra^lsdJM znSpIz9@bXRHuUPWSy=&>Q$IgmfTFjClA)*u#qRj z6P;25nMkwaSBvhu+Tz8*o-TXraIIP206qgqvLMRk!@!K*t-&>YhHAb~Tj z=>SR60&50hUVeHVk>)+|Uis(~+0>Xmeqid==O@Fy@|o3gD+-mhK5h5x>)XlJguBJf z9obP*8E)HiNB*+Y4b5(CtZfK&z#&vO<3B!ozkA4POj75qA4a?<%g_u!4A$`M*o7!Z z*a41}(~{^k-~@h22VVL-Z>2TCe=Y@u7q9GXyLG}O2mlvF5s>8z*?(R@R@H*F_D>~p VM3jxg4JZHr002ovPDHLkV1gaJph*A# literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blond/data/mode_hardlight.png b/cinelerra-5.1/plugins/theme_blond/data/mode_hardlight.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b9b64a4beb6a10d049d2d0e4830453c7db121f GIT binary patch literal 496 zcmV6wt|nKorNzTVxgdwpdzS2b6$4G zBJmQFGk+YmxV@R*eBUs4luRb^uSlg*%5fZk?SLk#Bu>`OYD#DJC%osPrmv#VS}SHG zVlP{Bm$v%!(z(O&YBIBOUfu5Qv1|2c1b|?mH=1ui*1s9(eF<8c06_piO((4F$P7RL z00kPz{*m%vNLU?>$!b1t`b$><07gQnrerznZW30NZ7m?}7T25G9g0L1_(%ErA)MQZ z*Vkn>ZZjLVJ`JR$S#b$wKLvm6cL)H3(W2jMou!l6ey(-C*;9dyrglGU_GZ?m&U2mG zpSF!|QsmRib;~fDw*N==ly%`_VLj$0(%CrEXw6AyE4!SU4-p7}0^#-Dc{)9wpO);v zEnx59O=}oac0>YFU~%|*b`n+yP`J7vm&X7o0&a?Z%V%Lp<$aT%$))>*cP+qj0|5Xk m7z_e1;YjO)OJ)g3DZc?!RgWV&+uq;+0000RO10Q`~#b`SU;jb3bH!e4L-M$;nCAXf!}GUM%vXux2b_ z)5LM?R2dywyfE?DI@d}6IrHoPF{ckdOBb)-duOly1{j5bzG}wRJu047Jgr>5zE!l@ z_Ne2RuMc@z_O!gFcPa2=0V4o{Si}`)M~br}h@@T^dxDrRy*N9HSd2v#FaY9VY;k4> zB2g^M|A``nu{p#Q#^wq~=E6vp>jDB&oY{%Vf&!^dOW$x9QCcAI<>FKWfZ>kX^Cv>! z>?J?&8ORGJlg14|Vu8{ko7dZm$DdPqo#t-edC@{wUQvGa`?)aiWnl><_@eFD0Qp`c zA{d8pRNqm3cmJ_2FP5m55QlNVs+_Gg$gSx@+ssejb_2d=kaThuV=;F1Dx1x@bd9mp zJ|JSP0I@nvH7fv(h`^VWA+>T%D$AxPBS^aliIbJfWPstmCh)PMh-s0CeNoaK+k=1a zhIHl0DAwPP3=j2To_Q2cH8w@RNdurZfYX>WBQY-q8(jr zh#)XE(WS{?xKI}AfJ0cSG(Oz?r+=H(1}8T0*MseGOp>4pfEcXdf5F8V{!c O0000v7zd@|cFu(0Z~zEnfB_H>rLi$^|4nbLM!tcu@+>My|2X-&r*0|a7%k5Nr~>SP(G|Yuu857+`Ul)#vb_hUi6k)WcbRDGzkTeXkcZHlO1~E`WLpA2&;ru zAPd4Oo8KPZsRh1NHb8%;qJ~s23}6!g&r@BU zY9~xGfR`sN$@uBS+}AUuHbw_Geq#m_L`0;}pr>B8?3QW{D(4xMxdYVe8Q3KtYV=wa zk#tN=w`Ps3`<+~xnr@w%Zp~If3#$(Tofp=zq@b#Uq2ealGl0&RS(t z2mynzu@$Ypf7NzcyNG(oh0007*Nkl=r?d%aMfkey$g|2D6NaOwpfTJ zCPXHgnfJYaP8XAzOyWko+{L};InTMzIrp9`>+9>h*Vx$DaCKdSmRS@z0v_CXbi(z^ zdtc1fAxaZWjM1rb^}_D=U;S3P(F}g|;x5{bu>uQv_TruSaQ|#A-M;@BU=&t*`}54L z|Gv{yrBs3iKzBB8&a3!vWw*$qfDr(h$HWFjR1b|JUZfcve0(eoRlop9HZunw1z@s%{DaS&Hr0EC;{j{SvUB&P)IYkSxZ<(2Jpp zvDeg>Q8$;1jiKMvjj;p8W(y+Yd?MQcM1w7(FH-8HSfLKE*}ioHRp;wdDOJAtz?g$f z()dl*ULB&-lb>x?gU#zko@**oYJnI#&RZ`}o&O2gdH!{Mu%=psuqu9tRHc0p)#)TL zg?h9a{BqNr)>MJIa&N)}vi7#v0Fq)S_S7+NX rxz94d6-5E0s-52X1G1_XthN6G0M0Q1Sc8`=00000NkvXXu0mjfIG$;V literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blond_cv/data/mode_and.png b/cinelerra-5.1/plugins/theme_blond_cv/data/mode_and.png new file mode 100644 index 0000000000000000000000000000000000000000..dbbc4e204819fd377226bfbf91ae3a1e993dba69 GIT binary patch literal 831 zcmV-F1Hk-=P)cpdsS-JWs6;QEI7S>eDQKtdHl6`?(WVi0Mn zHgQzDw&VBwc87zT62zrqPBYs5=sP<*GqSzC&Hu8UogH5k1z0T!A}@#df$1!JWH4@oo^rX@9(W#**v;_^;z9l#A*>z;Ng?x^Do~8yumB&NzKo}FaX3I z%lcP0s7F2U&8>yj`^S?8FrBCM zR{!RYfFT}nsKX3U07+1Xdei}Xv;Ib}_Um42Hh0mO74FXNnrVA9<@8z;Ucfli6BdLD zvy;*ukMiL-5iv7~CaTtLGkj{qfI76cEQ$g|cT#yYvE&>gYb&mmj^5swET5#pdzXfj z$!Mb|s5f&+b|&qhH9IliFipXA_{+j*s!zUq>l{yR& zrI{T~PYTqTdK0Ib+6(1aNf}CW&;O~4cKfHI+gXVbz)XG8yYsUmih5B6e+CYcXHLX{ z0|p1x>%HdgpoIxw*u6ogq&t4J58@?8^dC4xP_L)WT~_w^X?{3LMNPm=MQk;Xqp5j? zrN$X$P%qAVpLn12yRIrH7g~h?VyO$4UK@`mqc?i8Y(YC!_JBnY1wjDL=lW`UcI}=0 zU;gMF9M$srV(ZO8Q|AJRLjX16b2!Xri^-PHJ#j&Z!rhPF&wjW!oKBA~b`pt2r!l#9 zMTx=UWkk#2SeOGIVf3sx{O;?{MP~(zImHR(oPNPt3E)$*AxC$~YLeD(;5pcpg?#{c zf#0jO&%SRsSq>!sT?+Q^a89~N62NC!2E;})zVrfeW)7Tle*?#iOa)DDO56Yd002ov JPDHLkV1n-oc~}4d literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blond_cv/data/mode_average.png b/cinelerra-5.1/plugins/theme_blond_cv/data/mode_average.png deleted file mode 100644 index 3edf8524135218ed830e1d7e3ad5d75f7ac7a161..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 840 zcmV-O1GoH%P)!Xy9y0_90WK~y-6os>;zT}2efe`n_0 zkG!OLCQ*!7sbUeN_(8QGl}a}%rKw0PZkj^VMaZJkg>+#>kh&2!6+zKODK11^X#};4 zMg$dYp$OU#7o|<5U#Lmjm*(Z(_wJqJ;=Z(rK@iVkhT+Wb{Qtw585tfP=6}V=$cW~7 z4wgox$bZF(Qd)&8%TmpFWZm4Jr_VHt1Q@Kh27217frZ@9{FMTUhS-V&A8rKHpx)ga zeQRwq_rTVNt{)ydw~VrC`gC&e{jUarSncicb4gqZsK8?Go4HFg?A`X~#`_m=`VSI# zc2h%~eDPENrP;W#7-I%F=#1(a8=8Imf&Ajt^vhGX6{d&=^tfFR(K%8mjA2LZq- z#-r==shRZH$zE0Y`a}=N`ny}*H9-^+3}l&YE2VQhQJn63p|Ru18)cA*@7J{2?!k5W zo8z--;_=#1Ca$(SAOryca31k-{SHopeemPUo}e z)eri!mY7*la_DH^<*RXJs!|T7c1yWjYKVB8KXkNyayn7Z=#IrS=E|HNc(?CbGeUgT zKEvBe+koKo?B!(gRAOdh&u9B~=5LHQto^IX#VqWe$xiSc@PXUhlM3L0JIBUKay_V5MJI@-t40DHnb%SZ3(B(>U*EN z->*2tV3~4Pw5n9tDl(kK;-GGcM=M?B0F~Y;oPf~#hO}K zwt|IVW`+TR3GCg@@Kb^#P2|RfhL8b@aD6^+eEZ43ecp1ijC_$+Mk}Xi0ccE;5~U<5 zaTh3;ev!6qrg~LpioyNIYhF4gSAPn&a+wjgqX^I>Nq|u64y%}d3vcGZd;d2uj59pP SC9Kf^0000?P)C-d?OQJ&LUtxJ6-CT>J@MfGE zUA=YTt@FMgj%fXfn5i#zc;kSjAg%ygB)yp>=Bd}4-~fY1<{!k7>Vv9Kw86-Hc-*>)HQj1A?8rkPq<o-I8v`Ob$js)fBn*SYU5acef`p}b^gP`NO$Fj&;dNcdMjOi`f$%-XDL~SJ8zB`1tDMoKoqB3 zIr%W&azwJ=Tq6qMD90Q?N5C7bNoS6gX Z+)woy?36)5Dv|&I002ovPDHLkV1h8`Kc@fy literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blond_cv/data/mode_difference.png b/cinelerra-5.1/plugins/theme_blond_cv/data/mode_difference.png new file mode 100644 index 0000000000000000000000000000000000000000..c036b9d9555ef2e374470466b8e1aa5f33f69444 GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa&H|6fVg?3*gA5FU){JG5i7Y@t z_7YEDSM~>-(xQBt(_F4^0SayQba4#PIDdDNE!QCjf!6(Z*9dBRDn_$i(VOluG5U#s zr8nQk?GYEfbJCS>ED`8#a5>rEDwrhYxsv%Z&*#0B{A~aBAF=b?6Y*N|0i%$HZStSk zNjVJm*M8M#bg^YrKjX7$X*p_mIxl!#?&mw<4h2Q;y7fP1X)avH$iyn(HgSf?gJz!eHX6?-yk|@Ia^@>M)pTdT1e>U7$x{~FY@(xz5M4!)#=YM9Y Y{HHm)YU=)5K<6`fy85}Sb4q9e01l34$N&HU literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blond_cv/data/mode_dodge.png b/cinelerra-5.1/plugins/theme_blond_cv/data/mode_dodge.png new file mode 100644 index 0000000000000000000000000000000000000000..68eed2ac21d5b799266d9e8eb1b83e245b7a4d8a GIT binary patch literal 895 zcmV-_1AzRAP)5zIo-g&I-8 zDE5mMD{Wevq$=rTl1w^p-n;L(m~n!LAYLxqb2#UJ&;R@n9GRJ!;eVak*;yCIF=#IE zBLAA#h?6i1+HUHlks9y4Q)TZRH(q<{taYv(4%j@m)BzNCMJMOWaf9-qXh0Z`GhvGf?bZ)qE=>7_T2*#ocH~;&@bY;}Rp}NY2qA`;@q7HaD>-b43B-g=+6KTIY)&yoxO^!* zu)oo$3l^^!OPaB7FuAniKKddLD5g+yO=%r)VKomb0_f0ves#$vy>eUX>xra^lsdJM znSpIz9@bXRHuUPWSy=&>Q$IgmfTFjClA)*u#qRj z6P;25nMkwaSBvhu+Tz8*o-TXraIIP206qgqvLMRk!@!K*t-&>YhHAb~Tj z=>SR60&50hUVeHVk>)+|Uis(~+0>Xmeqid==O@Fy@|o3gD+-mhK5h5x>)XlJguBJf z9obP*8E)HiNB*+Y4b5(CtZfK&z#&vO<3B!ozkA4POj75qA4a?<%g_u!4A$`M*o7!Z z*a41}(~{^k-~@h22VVL-Z>2TCe=Y@u7q9GXyLG}O2mlvF5s>8z*?(R@R@H*F_D>~p VM3jxg4JZHr002ovPDHLkV1gaJph*A# literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blond_cv/data/mode_hardlight.png b/cinelerra-5.1/plugins/theme_blond_cv/data/mode_hardlight.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b9b64a4beb6a10d049d2d0e4830453c7db121f GIT binary patch literal 496 zcmV6wt|nKorNzTVxgdwpdzS2b6$4G zBJmQFGk+YmxV@R*eBUs4luRb^uSlg*%5fZk?SLk#Bu>`OYD#DJC%osPrmv#VS}SHG zVlP{Bm$v%!(z(O&YBIBOUfu5Qv1|2c1b|?mH=1ui*1s9(eF<8c06_piO((4F$P7RL z00kPz{*m%vNLU?>$!b1t`b$><07gQnrerznZW30NZ7m?}7T25G9g0L1_(%ErA)MQZ z*Vkn>ZZjLVJ`JR$S#b$wKLvm6cL)H3(W2jMou!l6ey(-C*;9dyrglGU_GZ?m&U2mG zpSF!|QsmRib;~fDw*N==ly%`_VLj$0(%CrEXw6AyE4!SU4-p7}0^#-Dc{)9wpO);v zEnx59O=}oac0>YFU~%|*b`n+yP`J7vm&X7o0&a?Z%V%Lp<$aT%$))>*cP+qj0|5Xk m7z_e1;YjO)OJ)g3DZc?!RgWV&+uq;+0000RO10Q`~#b`SU;jb3bH!e4L-M$;nCAXf!}GUM%vXux2b_ z)5LM?R2dywyfE?DI@d}6IrHoPF{ckdOBb)-duOly1{j5bzG}wRJu047Jgr>5zE!l@ z_Ne2RuMc@z_O!gFcPa2=0V4o{Si}`)M~br}h@@T^dxDrRy*N9HSd2v#FaY9VY;k4> zB2g^M|A``nu{p#Q#^wq~=E6vp>jDB&oY{%Vf&!^dOW$x9QCcAI<>FKWfZ>kX^Cv>! z>?J?&8ORGJlg14|Vu8{ko7dZm$DdPqo#t-edC@{wUQvGa`?)aiWnl><_@eFD0Qp`c zA{d8pRNqm3cmJ_2FP5m55QlNVs+_Gg$gSx@+ssejb_2d=kaThuV=;F1Dx1x@bd9mp zJ|JSP0I@nvH7fv(h`^VWA+>T%D$AxPBS^aliIbJfWPstmCh)PMh-s0CeNoaK+k=1a zhIHl0DAwPP3=j2To_Q2cH8w@RNdurZfYX>WBQY-q8(jr zh#)XE(WS{?xKI}AfJ0cSG(Oz?r+=H(1}8T0*MseGOp>4pfEcXdf5F8V{!c O0000v7zd@|cFu(0Z~zEnfB_H>rLi$^|4nbLM!tcu@+>My|2X-&r*0|a7%k5Nr~>SP(G|Yuu857+`Ul)#vb_hUi6k)WcbRDGzkTeXkcZHlO1~E`WLpA2&;ru zAPd4Oo8KPZsRh1NHb8%;qJ~s23}6!g&r@BU zY9~xGfR`sN$@uBS+}AUuHbw_Geq#m_L`0;}pr>B8?3QW{D(4xMxdYVe8Q3KtYV=wa zk#tN=w`Ps3`<+~xnr@w%Zp~If3#$(Tofp=zq@b#Uq2ealGl0&RS(t z2mynzu@$Ypf7NzcyNG(oh0007*Nkl=r?d%aMfkey$g|2D6NaOwpfTJ zCPXHgnfJYaP8XAzOyWko+{L};InTMzIrp9`>+9>h*Vx$DaCKdSmRS@z0v_CXbi(z^ zdtc1fAxaZWjM1rb^}_D=U;S3P(F}g|;x5{bu>uQv_TruSaQ|#A-M;@BU=&t*`}54L z|Gv{yrBs3iKzBB8&a3!vWw*$qfDr(h$HWFjR1b|JUZfcve0(eoRlop9HZunw1z@s%{DaS&Hr0EC;{j{SvUB&P)IYkSxZ<(2Jpp zvDeg>Q8$;1jiKMvjj;p8W(y+Yd?MQcM1w7(FH-8HSfLKE*}ioHRp;wdDOJAtz?g$f z()dl*ULB&-lb>x?gU#zko@**oYJnI#&RZ`}o&O2gdH!{Mu%=psuqu9tRHc0p)#)TL zg?h9a{BqNr)>MJIa&N)}vi7#v0Fq)S_S7+NX rxz94d6-5E0s-52X1G1_XthN6G0M0Q1Sc8`=00000NkvXXu0mjfIG$;V literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blue/data/mode_and.png b/cinelerra-5.1/plugins/theme_blue/data/mode_and.png new file mode 100644 index 0000000000000000000000000000000000000000..dbbc4e204819fd377226bfbf91ae3a1e993dba69 GIT binary patch literal 831 zcmV-F1Hk-=P)cpdsS-JWs6;QEI7S>eDQKtdHl6`?(WVi0Mn zHgQzDw&VBwc87zT62zrqPBYs5=sP<*GqSzC&Hu8UogH5k1z0T!A}@#df$1!JWH4@oo^rX@9(W#**v;_^;z9l#A*>z;Ng?x^Do~8yumB&NzKo}FaX3I z%lcP0s7F2U&8>yj`^S?8FrBCM zR{!RYfFT}nsKX3U07+1Xdei}Xv;Ib}_Um42Hh0mO74FXNnrVA9<@8z;Ucfli6BdLD zvy;*ukMiL-5iv7~CaTtLGkj{qfI76cEQ$g|cT#yYvE&>gYb&mmj^5swET5#pdzXfj z$!Mb|s5f&+b|&qhH9IliFipXA_{+j*s!zUq>l{yR& zrI{T~PYTqTdK0Ib+6(1aNf}CW&;O~4cKfHI+gXVbz)XG8yYsUmih5B6e+CYcXHLX{ z0|p1x>%HdgpoIxw*u6ogq&t4J58@?8^dC4xP_L)WT~_w^X?{3LMNPm=MQk;Xqp5j? zrN$X$P%qAVpLn12yRIrH7g~h?VyO$4UK@`mqc?i8Y(YC!_JBnY1wjDL=lW`UcI}=0 zU;gMF9M$srV(ZO8Q|AJRLjX16b2!Xri^-PHJ#j&Z!rhPF&wjW!oKBA~b`pt2r!l#9 zMTx=UWkk#2SeOGIVf3sx{O;?{MP~(zImHR(oPNPt3E)$*AxC$~YLeD(;5pcpg?#{c zf#0jO&%SRsSq>!sT?+Q^a89~N62NC!2E;})zVrfeW)7Tle*?#iOa)DDO56Yd002ov JPDHLkV1n-oc~}4d literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blue/data/mode_average.png b/cinelerra-5.1/plugins/theme_blue/data/mode_average.png deleted file mode 100644 index 3edf8524135218ed830e1d7e3ad5d75f7ac7a161..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 840 zcmV-O1GoH%P)!Xy9y0_90WK~y-6os>;zT}2efe`n_0 zkG!OLCQ*!7sbUeN_(8QGl}a}%rKw0PZkj^VMaZJkg>+#>kh&2!6+zKODK11^X#};4 zMg$dYp$OU#7o|<5U#Lmjm*(Z(_wJqJ;=Z(rK@iVkhT+Wb{Qtw585tfP=6}V=$cW~7 z4wgox$bZF(Qd)&8%TmpFWZm4Jr_VHt1Q@Kh27217frZ@9{FMTUhS-V&A8rKHpx)ga zeQRwq_rTVNt{)ydw~VrC`gC&e{jUarSncicb4gqZsK8?Go4HFg?A`X~#`_m=`VSI# zc2h%~eDPENrP;W#7-I%F=#1(a8=8Imf&Ajt^vhGX6{d&=^tfFR(K%8mjA2LZq- z#-r==shRZH$zE0Y`a}=N`ny}*H9-^+3}l&YE2VQhQJn63p|Ru18)cA*@7J{2?!k5W zo8z--;_=#1Ca$(SAOryca31k-{SHopeemPUo}e z)eri!mY7*la_DH^<*RXJs!|T7c1yWjYKVB8KXkNyayn7Z=#IrS=E|HNc(?CbGeUgT zKEvBe+koKo?B!(gRAOdh&u9B~=5LHQto^IX#VqWe$xiSc@PXUhlM3L0JIBUKay_V5MJI@-t40DHnb%SZ3(B(>U*EN z->*2tV3~4Pw5n9tDl(kK;-GGcM=M?B0F~Y;oPf~#hO}K zwt|IVW`+TR3GCg@@Kb^#P2|RfhL8b@aD6^+eEZ43ecp1ijC_$+Mk}Xi0ccE;5~U<5 zaTh3;ev!6qrg~LpioyNIYhF4gSAPn&a+wjgqX^I>Nq|u64y%}d3vcGZd;d2uj59pP SC9Kf^0000?P)C-d?OQJ&LUtxJ6-CT>J@MfGE zUA=YTt@FMgj%fXfn5i#zc;kSjAg%ygB)yp>=Bd}4-~fY1<{!k7>Vv9Kw86-Hc-*>)HQj1A?8rkPq<o-I8v`Ob$js)fBn*SYU5acef`p}b^gP`NO$Fj&;dNcdMjOi`f$%-XDL~SJ8zB`1tDMoKoqB3 zIr%W&azwJ=Tq6qMD90Q?N5C7bNoS6gX Z+)woy?36)5Dv|&I002ovPDHLkV1h8`Kc@fy literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blue/data/mode_difference.png b/cinelerra-5.1/plugins/theme_blue/data/mode_difference.png new file mode 100644 index 0000000000000000000000000000000000000000..c036b9d9555ef2e374470466b8e1aa5f33f69444 GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa&H|6fVg?3*gA5FU){JG5i7Y@t z_7YEDSM~>-(xQBt(_F4^0SayQba4#PIDdDNE!QCjf!6(Z*9dBRDn_$i(VOluG5U#s zr8nQk?GYEfbJCS>ED`8#a5>rEDwrhYxsv%Z&*#0B{A~aBAF=b?6Y*N|0i%$HZStSk zNjVJm*M8M#bg^YrKjX7$X*p_mIxl!#?&mw<4h2Q;y7fP1X)avH$iyn(HgSf?gJz!eHX6?-yk|@Ia^@>M)pTdT1e>U7$x{~FY@(xz5M4!)#=YM9Y Y{HHm)YU=)5K<6`fy85}Sb4q9e01l34$N&HU literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blue/data/mode_dodge.png b/cinelerra-5.1/plugins/theme_blue/data/mode_dodge.png new file mode 100644 index 0000000000000000000000000000000000000000..68eed2ac21d5b799266d9e8eb1b83e245b7a4d8a GIT binary patch literal 895 zcmV-_1AzRAP)5zIo-g&I-8 zDE5mMD{Wevq$=rTl1w^p-n;L(m~n!LAYLxqb2#UJ&;R@n9GRJ!;eVak*;yCIF=#IE zBLAA#h?6i1+HUHlks9y4Q)TZRH(q<{taYv(4%j@m)BzNCMJMOWaf9-qXh0Z`GhvGf?bZ)qE=>7_T2*#ocH~;&@bY;}Rp}NY2qA`;@q7HaD>-b43B-g=+6KTIY)&yoxO^!* zu)oo$3l^^!OPaB7FuAniKKddLD5g+yO=%r)VKomb0_f0ves#$vy>eUX>xra^lsdJM znSpIz9@bXRHuUPWSy=&>Q$IgmfTFjClA)*u#qRj z6P;25nMkwaSBvhu+Tz8*o-TXraIIP206qgqvLMRk!@!K*t-&>YhHAb~Tj z=>SR60&50hUVeHVk>)+|Uis(~+0>Xmeqid==O@Fy@|o3gD+-mhK5h5x>)XlJguBJf z9obP*8E)HiNB*+Y4b5(CtZfK&z#&vO<3B!ozkA4POj75qA4a?<%g_u!4A$`M*o7!Z z*a41}(~{^k-~@h22VVL-Z>2TCe=Y@u7q9GXyLG}O2mlvF5s>8z*?(R@R@H*F_D>~p VM3jxg4JZHr002ovPDHLkV1gaJph*A# literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blue/data/mode_hardlight.png b/cinelerra-5.1/plugins/theme_blue/data/mode_hardlight.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b9b64a4beb6a10d049d2d0e4830453c7db121f GIT binary patch literal 496 zcmV6wt|nKorNzTVxgdwpdzS2b6$4G zBJmQFGk+YmxV@R*eBUs4luRb^uSlg*%5fZk?SLk#Bu>`OYD#DJC%osPrmv#VS}SHG zVlP{Bm$v%!(z(O&YBIBOUfu5Qv1|2c1b|?mH=1ui*1s9(eF<8c06_piO((4F$P7RL z00kPz{*m%vNLU?>$!b1t`b$><07gQnrerznZW30NZ7m?}7T25G9g0L1_(%ErA)MQZ z*Vkn>ZZjLVJ`JR$S#b$wKLvm6cL)H3(W2jMou!l6ey(-C*;9dyrglGU_GZ?m&U2mG zpSF!|QsmRib;~fDw*N==ly%`_VLj$0(%CrEXw6AyE4!SU4-p7}0^#-Dc{)9wpO);v zEnx59O=}oac0>YFU~%|*b`n+yP`J7vm&X7o0&a?Z%V%Lp<$aT%$))>*cP+qj0|5Xk m7z_e1;YjO)OJ)g3DZc?!RgWV&+uq;+0000RO10Q`~#b`SU;jb3bH!e4L-M$;nCAXf!}GUM%vXux2b_ z)5LM?R2dywyfE?DI@d}6IrHoPF{ckdOBb)-duOly1{j5bzG}wRJu047Jgr>5zE!l@ z_Ne2RuMc@z_O!gFcPa2=0V4o{Si}`)M~br}h@@T^dxDrRy*N9HSd2v#FaY9VY;k4> zB2g^M|A``nu{p#Q#^wq~=E6vp>jDB&oY{%Vf&!^dOW$x9QCcAI<>FKWfZ>kX^Cv>! z>?J?&8ORGJlg14|Vu8{ko7dZm$DdPqo#t-edC@{wUQvGa`?)aiWnl><_@eFD0Qp`c zA{d8pRNqm3cmJ_2FP5m55QlNVs+_Gg$gSx@+ssejb_2d=kaThuV=;F1Dx1x@bd9mp zJ|JSP0I@nvH7fv(h`^VWA+>T%D$AxPBS^aliIbJfWPstmCh)PMh-s0CeNoaK+k=1a zhIHl0DAwPP3=j2To_Q2cH8w@RNdurZfYX>WBQY-q8(jr zh#)XE(WS{?xKI}AfJ0cSG(Oz?r+=H(1}8T0*MseGOp>4pfEcXdf5F8V{!c O0000v7zd@|cFu(0Z~zEnfB_H>rLi$^|4nbLM!tcu@+>My|2X-&r*0|a7%k5Nr~>SP(G|Yuu857+`Ul)#vb_hUi6k)WcbRDGzkTeXkcZHlO1~E`WLpA2&;ru zAPd4Oo8KPZsRh1NHb8%;qJ~s23}6!g&r@BU zY9~xGfR`sN$@uBS+}AUuHbw_Geq#m_L`0;}pr>B8?3QW{D(4xMxdYVe8Q3KtYV=wa zk#tN=w`Ps3`<+~xnr@w%Zp~If3#$(Tofp=zq@b#Uq2ealGl0&RS(t z2mynzu@$Ypf7NzcyNG(oh0007*Nkl=r?d%aMfkey$g|2D6NaOwpfTJ zCPXHgnfJYaP8XAzOyWko+{L};InTMzIrp9`>+9>h*Vx$DaCKdSmRS@z0v_CXbi(z^ zdtc1fAxaZWjM1rb^}_D=U;S3P(F}g|;x5{bu>uQv_TruSaQ|#A-M;@BU=&t*`}54L z|Gv{yrBs3iKzBB8&a3!vWw*$qfDr(h$HWFjR1b|JUZfcve0(eoRlop9HZunw1z@s%{DaS&Hr0EC;{j{SvUB&P)IYkSxZ<(2Jpp zvDeg>Q8$;1jiKMvjj;p8W(y+Yd?MQcM1w7(FH-8HSfLKE*}ioHRp;wdDOJAtz?g$f z()dl*ULB&-lb>x?gU#zko@**oYJnI#&RZ`}o&O2gdH!{Mu%=psuqu9tRHc0p)#)TL zg?h9a{BqNr)>MJIa&N)}vi7#v0Fq)S_S7+NX rxz94d6-5E0s-52X1G1_XthN6G0M0Q1Sc8`=00000NkvXXu0mjfIG$;V literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blue_dot/data/mode_and.png b/cinelerra-5.1/plugins/theme_blue_dot/data/mode_and.png new file mode 100644 index 0000000000000000000000000000000000000000..dbbc4e204819fd377226bfbf91ae3a1e993dba69 GIT binary patch literal 831 zcmV-F1Hk-=P)cpdsS-JWs6;QEI7S>eDQKtdHl6`?(WVi0Mn zHgQzDw&VBwc87zT62zrqPBYs5=sP<*GqSzC&Hu8UogH5k1z0T!A}@#df$1!JWH4@oo^rX@9(W#**v;_^;z9l#A*>z;Ng?x^Do~8yumB&NzKo}FaX3I z%lcP0s7F2U&8>yj`^S?8FrBCM zR{!RYfFT}nsKX3U07+1Xdei}Xv;Ib}_Um42Hh0mO74FXNnrVA9<@8z;Ucfli6BdLD zvy;*ukMiL-5iv7~CaTtLGkj{qfI76cEQ$g|cT#yYvE&>gYb&mmj^5swET5#pdzXfj z$!Mb|s5f&+b|&qhH9IliFipXA_{+j*s!zUq>l{yR& zrI{T~PYTqTdK0Ib+6(1aNf}CW&;O~4cKfHI+gXVbz)XG8yYsUmih5B6e+CYcXHLX{ z0|p1x>%HdgpoIxw*u6ogq&t4J58@?8^dC4xP_L)WT~_w^X?{3LMNPm=MQk;Xqp5j? zrN$X$P%qAVpLn12yRIrH7g~h?VyO$4UK@`mqc?i8Y(YC!_JBnY1wjDL=lW`UcI}=0 zU;gMF9M$srV(ZO8Q|AJRLjX16b2!Xri^-PHJ#j&Z!rhPF&wjW!oKBA~b`pt2r!l#9 zMTx=UWkk#2SeOGIVf3sx{O;?{MP~(zImHR(oPNPt3E)$*AxC$~YLeD(;5pcpg?#{c zf#0jO&%SRsSq>!sT?+Q^a89~N62NC!2E;})zVrfeW)7Tle*?#iOa)DDO56Yd002ov JPDHLkV1n-oc~}4d literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blue_dot/data/mode_average.png b/cinelerra-5.1/plugins/theme_blue_dot/data/mode_average.png deleted file mode 100644 index 0b2fdef3cdeb7c69039b6e24c97e90dac21caba2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1028 zcmV+f1pE7mP)xN#0007EP)t-s`_feV z(^=^0>*(s~HZ?H(#|eIIC4O!&er_^;ZZm##EPi$^{M03FPA}Sg2$?yA$_+_LNBzqTwU<3fOG>qvJduDX{m>Qt(;WTNCF{mi>&I37*d^=CV(RMZ zI5{y&Mk`82EnHJ7TvIIm#|Zw%3V?1T{>u*j%MgHZEJ{jB{>%&h%oE6_9!gA0{>~Eq z&J_O75dP2_{?Z%%(<1)V9{$xK{?{b_*emPn>Few3|HT4tUnBp<1vxn{IXN-gt`+~t z3IECnx0fcjm@G?6NlQyhx0yHp&lCU87yr>5|I!!#(jB*TP^a$7MO%9bzeGTSSn*% zEr)e2QBFnAsvEtaD4B>Z^T=QG&sVFfsjI82;Q{;&SQ$;#cOF;Ic33qBX zQ&B~mhAHKW2zX#RR7^kjqzd-M5L8k|_ooQ=sR`1xE9Q#{d1E?NPCmh%6Vs{?uCA_& zdoAU?9acs+Xk02*Pd`LMFXp)w_{tUd&{p`;C3{{zS4B7HvPgSoH;s2BS5Q9r#Sd3f zKl#WES5!e)R71n1L$R7F`OjAQ&{TX{H8eFa#GMgpT_~W199UC8)~*<`mO`?ZKIp_I z`p{SU(_HG33hI*xM?x+&HZgr^H~Ym2eQP7Llozv_CY+OhA^-pZUP(kjR2Y?GXvG9` z7`(lDCZm8H{bmNqZsFS6#cLrTwzhVUYYkAa+L?*T(E$STnV635*x1A%$Q6NDMrX+W*mXpV|SZB@FbSq$r*#H#eWQs5lRaZW-ewW=55%B_k50IcBQ-qoB zYX0ro0`@y6=~Oa#?gk1TV~+4OUBbq%%&$>qXi~`^w+<+{iYX$%&oAD^{-}|kpG+~6 z&l;eUW-v#{`sXfCR#sM+QEGW!ei8Ok_UF9TW}(VPRp@xEAs6?F0%g zk6>m_v4wzoX6EgiK!V#EltK?O9@w&U>DH|b@(PVBfr7@o?Nhrl4)vw+@uf{aoH21q yR%SDUw^+yg`SVwR!F&)%2L^I$Ya1#6Mh5`*gqY)76Y`q?0000?P)C-d?OQJ&LUtxJ6-CT>J@MfGE zUA=YTt@FMgj%fXfn5i#zc;kSjAg%ygB)yp>=Bd}4-~fY1<{!k7>Vv9Kw86-Hc-*>)HQj1A?8rkPq<o-I8v`Ob$js)fBn*SYU5acef`p}b^gP`NO$Fj&;dNcdMjOi`f$%-XDL~SJ8zB`1tDMoKoqB3 zIr%W&azwJ=Tq6qMD90Q?N5C7bNoS6gX Z+)woy?36)5Dv|&I002ovPDHLkV1h8`Kc@fy literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blue_dot/data/mode_difference.png b/cinelerra-5.1/plugins/theme_blue_dot/data/mode_difference.png new file mode 100644 index 0000000000000000000000000000000000000000..c036b9d9555ef2e374470466b8e1aa5f33f69444 GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa&H|6fVg?3*gA5FU){JG5i7Y@t z_7YEDSM~>-(xQBt(_F4^0SayQba4#PIDdDNE!QCjf!6(Z*9dBRDn_$i(VOluG5U#s zr8nQk?GYEfbJCS>ED`8#a5>rEDwrhYxsv%Z&*#0B{A~aBAF=b?6Y*N|0i%$HZStSk zNjVJm*M8M#bg^YrKjX7$X*p_mIxl!#?&mw<4h2Q;y7fP1X)avH$iyn(HgSf?gJz!eHX6?-yk|@Ia^@>M)pTdT1e>U7$x{~FY@(xz5M4!)#=YM9Y Y{HHm)YU=)5K<6`fy85}Sb4q9e01l34$N&HU literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blue_dot/data/mode_dodge.png b/cinelerra-5.1/plugins/theme_blue_dot/data/mode_dodge.png new file mode 100644 index 0000000000000000000000000000000000000000..68eed2ac21d5b799266d9e8eb1b83e245b7a4d8a GIT binary patch literal 895 zcmV-_1AzRAP)5zIo-g&I-8 zDE5mMD{Wevq$=rTl1w^p-n;L(m~n!LAYLxqb2#UJ&;R@n9GRJ!;eVak*;yCIF=#IE zBLAA#h?6i1+HUHlks9y4Q)TZRH(q<{taYv(4%j@m)BzNCMJMOWaf9-qXh0Z`GhvGf?bZ)qE=>7_T2*#ocH~;&@bY;}Rp}NY2qA`;@q7HaD>-b43B-g=+6KTIY)&yoxO^!* zu)oo$3l^^!OPaB7FuAniKKddLD5g+yO=%r)VKomb0_f0ves#$vy>eUX>xra^lsdJM znSpIz9@bXRHuUPWSy=&>Q$IgmfTFjClA)*u#qRj z6P;25nMkwaSBvhu+Tz8*o-TXraIIP206qgqvLMRk!@!K*t-&>YhHAb~Tj z=>SR60&50hUVeHVk>)+|Uis(~+0>Xmeqid==O@Fy@|o3gD+-mhK5h5x>)XlJguBJf z9obP*8E)HiNB*+Y4b5(CtZfK&z#&vO<3B!ozkA4POj75qA4a?<%g_u!4A$`M*o7!Z z*a41}(~{^k-~@h22VVL-Z>2TCe=Y@u7q9GXyLG}O2mlvF5s>8z*?(R@R@H*F_D>~p VM3jxg4JZHr002ovPDHLkV1gaJph*A# literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_blue_dot/data/mode_hardlight.png b/cinelerra-5.1/plugins/theme_blue_dot/data/mode_hardlight.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b9b64a4beb6a10d049d2d0e4830453c7db121f GIT binary patch literal 496 zcmV6wt|nKorNzTVxgdwpdzS2b6$4G zBJmQFGk+YmxV@R*eBUs4luRb^uSlg*%5fZk?SLk#Bu>`OYD#DJC%osPrmv#VS}SHG zVlP{Bm$v%!(z(O&YBIBOUfu5Qv1|2c1b|?mH=1ui*1s9(eF<8c06_piO((4F$P7RL z00kPz{*m%vNLU?>$!b1t`b$><07gQnrerznZW30NZ7m?}7T25G9g0L1_(%ErA)MQZ z*Vkn>ZZjLVJ`JR$S#b$wKLvm6cL)H3(W2jMou!l6ey(-C*;9dyrglGU_GZ?m&U2mG zpSF!|QsmRib;~fDw*N==ly%`_VLj$0(%CrEXw6AyE4!SU4-p7}0^#-Dc{)9wpO);v zEnx59O=}oac0>YFU~%|*b`n+yP`J7vm&X7o0&a?Z%V%Lp<$aT%$))>*cP+qj0|5Xk m7z_e1;YjO)OJ)g3DZc?!RgWV&+uq;+0000RO10Q`~#b`SU;jb3bH!e4L-M$;nCAXf!}GUM%vXux2b_ z)5LM?R2dywyfE?DI@d}6IrHoPF{ckdOBb)-duOly1{j5bzG}wRJu047Jgr>5zE!l@ z_Ne2RuMc@z_O!gFcPa2=0V4o{Si}`)M~br}h@@T^dxDrRy*N9HSd2v#FaY9VY;k4> zB2g^M|A``nu{p#Q#^wq~=E6vp>jDB&oY{%Vf&!^dOW$x9QCcAI<>FKWfZ>kX^Cv>! z>?J?&8ORGJlg14|Vu8{ko7dZm$DdPqo#t-edC@{wUQvGa`?)aiWnl><_@eFD0Qp`c zA{d8pRNqm3cmJ_2FP5m55QlNVs+_Gg$gSx@+ssejb_2d=kaThuV=;F1Dx1x@bd9mp zJ|JSP0I@nvH7fv(h`^VWA+>T%D$AxPBS^aliIbJfWPstmCh)PMh-s0CeNoaK+k=1a zhIHl0DAwPP3=j2To_Q2cH8w@RNdurZfYX>WBQY-q8(jr zh#)XE(WS{?xKI}AfJ0cSG(Oz?r+=H(1}8T0*MseGOp>4pfEcXdf5F8V{!c O0000v7zd@|cFu(0Z~zEnfB_H>rLi$^|4nbLM!tcu@+>My|2X-&r*0|a7%k5Nr~>SP(G|Yuu857+`Ul)#vb_hUi6k)WcbRDGzkTeXkcZHlO1~E`WLpA2&;ru zAPd4Oo8KPZsRh1NHb8%;qJ~s23}6!g&r@BU zY9~xGfR`sN$@uBS+}AUuHbw_Geq#m_L`0;}pr>B8?3QW{D(4xMxdYVe8Q3KtYV=wa zk#tN=w`Ps3`<+~xnr@w%Zp~If3#$(Tofp=zq@b#Uq2ealGl0&RS(t z2mynzu@$Ypf7NzcyNG(oh0007*Nkl=r?d%aMfkey$g|2D6NaOwpfTJ zCPXHgnfJYaP8XAzOyWko+{L};InTMzIrp9`>+9>h*Vx$DaCKdSmRS@z0v_CXbi(z^ zdtc1fAxaZWjM1rb^}_D=U;S3P(F}g|;x5{bu>uQv_TruSaQ|#A-M;@BU=&t*`}54L z|Gv{yrBs3iKzBB8&a3!vWw*$qfDr(h$HWFjR1b|JUZfcve0(eoRlop9HZunw1z@s%{DaS&Hr0EC;{j{SvUB&P)IYkSxZ<(2Jpp zvDeg>Q8$;1jiKMvjj;p8W(y+Yd?MQcM1w7(FH-8HSfLKE*}ioHRp;wdDOJAtz?g$f z()dl*ULB&-lb>x?gU#zko@**oYJnI#&RZ`}o&O2gdH!{Mu%=psuqu9tRHc0p)#)TL zg?h9a{BqNr)>MJIa&N)}vi7#v0Fq)S_S7+NX rxz94d6-5E0s-52X1G1_XthN6G0M0Q1Sc8`=00000NkvXXu0mjfIG$;V literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_bright/data/mode_and.png b/cinelerra-5.1/plugins/theme_bright/data/mode_and.png new file mode 100644 index 0000000000000000000000000000000000000000..dbbc4e204819fd377226bfbf91ae3a1e993dba69 GIT binary patch literal 831 zcmV-F1Hk-=P)cpdsS-JWs6;QEI7S>eDQKtdHl6`?(WVi0Mn zHgQzDw&VBwc87zT62zrqPBYs5=sP<*GqSzC&Hu8UogH5k1z0T!A}@#df$1!JWH4@oo^rX@9(W#**v;_^;z9l#A*>z;Ng?x^Do~8yumB&NzKo}FaX3I z%lcP0s7F2U&8>yj`^S?8FrBCM zR{!RYfFT}nsKX3U07+1Xdei}Xv;Ib}_Um42Hh0mO74FXNnrVA9<@8z;Ucfli6BdLD zvy;*ukMiL-5iv7~CaTtLGkj{qfI76cEQ$g|cT#yYvE&>gYb&mmj^5swET5#pdzXfj z$!Mb|s5f&+b|&qhH9IliFipXA_{+j*s!zUq>l{yR& zrI{T~PYTqTdK0Ib+6(1aNf}CW&;O~4cKfHI+gXVbz)XG8yYsUmih5B6e+CYcXHLX{ z0|p1x>%HdgpoIxw*u6ogq&t4J58@?8^dC4xP_L)WT~_w^X?{3LMNPm=MQk;Xqp5j? zrN$X$P%qAVpLn12yRIrH7g~h?VyO$4UK@`mqc?i8Y(YC!_JBnY1wjDL=lW`UcI}=0 zU;gMF9M$srV(ZO8Q|AJRLjX16b2!Xri^-PHJ#j&Z!rhPF&wjW!oKBA~b`pt2r!l#9 zMTx=UWkk#2SeOGIVf3sx{O;?{MP~(zImHR(oPNPt3E)$*AxC$~YLeD(;5pcpg?#{c zf#0jO&%SRsSq>!sT?+Q^a89~N62NC!2E;})zVrfeW)7Tle*?#iOa)DDO56Yd002ov JPDHLkV1n-oc~}4d literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_bright/data/mode_average.png b/cinelerra-5.1/plugins/theme_bright/data/mode_average.png deleted file mode 100644 index 3edf8524135218ed830e1d7e3ad5d75f7ac7a161..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 840 zcmV-O1GoH%P)!Xy9y0_90WK~y-6os>;zT}2efe`n_0 zkG!OLCQ*!7sbUeN_(8QGl}a}%rKw0PZkj^VMaZJkg>+#>kh&2!6+zKODK11^X#};4 zMg$dYp$OU#7o|<5U#Lmjm*(Z(_wJqJ;=Z(rK@iVkhT+Wb{Qtw585tfP=6}V=$cW~7 z4wgox$bZF(Qd)&8%TmpFWZm4Jr_VHt1Q@Kh27217frZ@9{FMTUhS-V&A8rKHpx)ga zeQRwq_rTVNt{)ydw~VrC`gC&e{jUarSncicb4gqZsK8?Go4HFg?A`X~#`_m=`VSI# zc2h%~eDPENrP;W#7-I%F=#1(a8=8Imf&Ajt^vhGX6{d&=^tfFR(K%8mjA2LZq- z#-r==shRZH$zE0Y`a}=N`ny}*H9-^+3}l&YE2VQhQJn63p|Ru18)cA*@7J{2?!k5W zo8z--;_=#1Ca$(SAOryca31k-{SHopeemPUo}e z)eri!mY7*la_DH^<*RXJs!|T7c1yWjYKVB8KXkNyayn7Z=#IrS=E|HNc(?CbGeUgT zKEvBe+koKo?B!(gRAOdh&u9B~=5LHQto^IX#VqWe$xiSc@PXUhlM3L0JIBUKay_V5MJI@-t40DHnb%SZ3(B(>U*EN z->*2tV3~4Pw5n9tDl(kK;-GGcM=M?B0F~Y;oPf~#hO}K zwt|IVW`+TR3GCg@@Kb^#P2|RfhL8b@aD6^+eEZ43ecp1ijC_$+Mk}Xi0ccE;5~U<5 zaTh3;ev!6qrg~LpioyNIYhF4gSAPn&a+wjgqX^I>Nq|u64y%}d3vcGZd;d2uj59pP SC9Kf^0000?P)C-d?OQJ&LUtxJ6-CT>J@MfGE zUA=YTt@FMgj%fXfn5i#zc;kSjAg%ygB)yp>=Bd}4-~fY1<{!k7>Vv9Kw86-Hc-*>)HQj1A?8rkPq<o-I8v`Ob$js)fBn*SYU5acef`p}b^gP`NO$Fj&;dNcdMjOi`f$%-XDL~SJ8zB`1tDMoKoqB3 zIr%W&azwJ=Tq6qMD90Q?N5C7bNoS6gX Z+)woy?36)5Dv|&I002ovPDHLkV1h8`Kc@fy literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_bright/data/mode_difference.png b/cinelerra-5.1/plugins/theme_bright/data/mode_difference.png new file mode 100644 index 0000000000000000000000000000000000000000..c036b9d9555ef2e374470466b8e1aa5f33f69444 GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa&H|6fVg?3*gA5FU){JG5i7Y@t z_7YEDSM~>-(xQBt(_F4^0SayQba4#PIDdDNE!QCjf!6(Z*9dBRDn_$i(VOluG5U#s zr8nQk?GYEfbJCS>ED`8#a5>rEDwrhYxsv%Z&*#0B{A~aBAF=b?6Y*N|0i%$HZStSk zNjVJm*M8M#bg^YrKjX7$X*p_mIxl!#?&mw<4h2Q;y7fP1X)avH$iyn(HgSf?gJz!eHX6?-yk|@Ia^@>M)pTdT1e>U7$x{~FY@(xz5M4!)#=YM9Y Y{HHm)YU=)5K<6`fy85}Sb4q9e01l34$N&HU literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_bright/data/mode_dodge.png b/cinelerra-5.1/plugins/theme_bright/data/mode_dodge.png new file mode 100644 index 0000000000000000000000000000000000000000..68eed2ac21d5b799266d9e8eb1b83e245b7a4d8a GIT binary patch literal 895 zcmV-_1AzRAP)5zIo-g&I-8 zDE5mMD{Wevq$=rTl1w^p-n;L(m~n!LAYLxqb2#UJ&;R@n9GRJ!;eVak*;yCIF=#IE zBLAA#h?6i1+HUHlks9y4Q)TZRH(q<{taYv(4%j@m)BzNCMJMOWaf9-qXh0Z`GhvGf?bZ)qE=>7_T2*#ocH~;&@bY;}Rp}NY2qA`;@q7HaD>-b43B-g=+6KTIY)&yoxO^!* zu)oo$3l^^!OPaB7FuAniKKddLD5g+yO=%r)VKomb0_f0ves#$vy>eUX>xra^lsdJM znSpIz9@bXRHuUPWSy=&>Q$IgmfTFjClA)*u#qRj z6P;25nMkwaSBvhu+Tz8*o-TXraIIP206qgqvLMRk!@!K*t-&>YhHAb~Tj z=>SR60&50hUVeHVk>)+|Uis(~+0>Xmeqid==O@Fy@|o3gD+-mhK5h5x>)XlJguBJf z9obP*8E)HiNB*+Y4b5(CtZfK&z#&vO<3B!ozkA4POj75qA4a?<%g_u!4A$`M*o7!Z z*a41}(~{^k-~@h22VVL-Z>2TCe=Y@u7q9GXyLG}O2mlvF5s>8z*?(R@R@H*F_D>~p VM3jxg4JZHr002ovPDHLkV1gaJph*A# literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_bright/data/mode_hardlight.png b/cinelerra-5.1/plugins/theme_bright/data/mode_hardlight.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b9b64a4beb6a10d049d2d0e4830453c7db121f GIT binary patch literal 496 zcmV6wt|nKorNzTVxgdwpdzS2b6$4G zBJmQFGk+YmxV@R*eBUs4luRb^uSlg*%5fZk?SLk#Bu>`OYD#DJC%osPrmv#VS}SHG zVlP{Bm$v%!(z(O&YBIBOUfu5Qv1|2c1b|?mH=1ui*1s9(eF<8c06_piO((4F$P7RL z00kPz{*m%vNLU?>$!b1t`b$><07gQnrerznZW30NZ7m?}7T25G9g0L1_(%ErA)MQZ z*Vkn>ZZjLVJ`JR$S#b$wKLvm6cL)H3(W2jMou!l6ey(-C*;9dyrglGU_GZ?m&U2mG zpSF!|QsmRib;~fDw*N==ly%`_VLj$0(%CrEXw6AyE4!SU4-p7}0^#-Dc{)9wpO);v zEnx59O=}oac0>YFU~%|*b`n+yP`J7vm&X7o0&a?Z%V%Lp<$aT%$))>*cP+qj0|5Xk m7z_e1;YjO)OJ)g3DZc?!RgWV&+uq;+0000RO10Q`~#b`SU;jb3bH!e4L-M$;nCAXf!}GUM%vXux2b_ z)5LM?R2dywyfE?DI@d}6IrHoPF{ckdOBb)-duOly1{j5bzG}wRJu047Jgr>5zE!l@ z_Ne2RuMc@z_O!gFcPa2=0V4o{Si}`)M~br}h@@T^dxDrRy*N9HSd2v#FaY9VY;k4> zB2g^M|A``nu{p#Q#^wq~=E6vp>jDB&oY{%Vf&!^dOW$x9QCcAI<>FKWfZ>kX^Cv>! z>?J?&8ORGJlg14|Vu8{ko7dZm$DdPqo#t-edC@{wUQvGa`?)aiWnl><_@eFD0Qp`c zA{d8pRNqm3cmJ_2FP5m55QlNVs+_Gg$gSx@+ssejb_2d=kaThuV=;F1Dx1x@bd9mp zJ|JSP0I@nvH7fv(h`^VWA+>T%D$AxPBS^aliIbJfWPstmCh)PMh-s0CeNoaK+k=1a zhIHl0DAwPP3=j2To_Q2cH8w@RNdurZfYX>WBQY-q8(jr zh#)XE(WS{?xKI}AfJ0cSG(Oz?r+=H(1}8T0*MseGOp>4pfEcXdf5F8V{!c O0000v7zd@|cFu(0Z~zEnfB_H>rLi$^|4nbLM!tcu@+>My|2X-&r*0|a7%k5Nr~>SP(G|Yuu857+`Ul)#vb_hUi6k)WcbRDGzkTeXkcZHlO1~E`WLpA2&;ru zAPd4Oo8KPZsRh1NHb8%;qJ~s23}6!g&r@BU zY9~xGfR`sN$@uBS+}AUuHbw_Geq#m_L`0;}pr>B8?3QW{D(4xMxdYVe8Q3KtYV=wa zk#tN=w`Ps3`<+~xnr@w%Zp~If3#$(Tofp=zq@b#Uq2ealGl0&RS(t z2mynzu@$Ypf7NzcyNG(oh0007*Nkl=r?d%aMfkey$g|2D6NaOwpfTJ zCPXHgnfJYaP8XAzOyWko+{L};InTMzIrp9`>+9>h*Vx$DaCKdSmRS@z0v_CXbi(z^ zdtc1fAxaZWjM1rb^}_D=U;S3P(F}g|;x5{bu>uQv_TruSaQ|#A-M;@BU=&t*`}54L z|Gv{yrBs3iKzBB8&a3!vWw*$qfDr(h$HWFjR1b|JUZfcve0(eoRlop9HZunw1z@s%{DaS&Hr0EC;{j{SvUB&P)IYkSxZ<(2Jpp zvDeg>Q8$;1jiKMvjj;p8W(y+Yd?MQcM1w7(FH-8HSfLKE*}ioHRp;wdDOJAtz?g$f z()dl*ULB&-lb>x?gU#zko@**oYJnI#&RZ`}o&O2gdH!{Mu%=psuqu9tRHc0p)#)TL zg?h9a{BqNr)>MJIa&N)}vi7#v0Fq)S_S7+NX rxz94d6-5E0s-52X1G1_XthN6G0M0Q1Sc8`=00000NkvXXu0mjfIG$;V literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_hulk/data/mode_and.png b/cinelerra-5.1/plugins/theme_hulk/data/mode_and.png new file mode 100644 index 0000000000000000000000000000000000000000..dbbc4e204819fd377226bfbf91ae3a1e993dba69 GIT binary patch literal 831 zcmV-F1Hk-=P)cpdsS-JWs6;QEI7S>eDQKtdHl6`?(WVi0Mn zHgQzDw&VBwc87zT62zrqPBYs5=sP<*GqSzC&Hu8UogH5k1z0T!A}@#df$1!JWH4@oo^rX@9(W#**v;_^;z9l#A*>z;Ng?x^Do~8yumB&NzKo}FaX3I z%lcP0s7F2U&8>yj`^S?8FrBCM zR{!RYfFT}nsKX3U07+1Xdei}Xv;Ib}_Um42Hh0mO74FXNnrVA9<@8z;Ucfli6BdLD zvy;*ukMiL-5iv7~CaTtLGkj{qfI76cEQ$g|cT#yYvE&>gYb&mmj^5swET5#pdzXfj z$!Mb|s5f&+b|&qhH9IliFipXA_{+j*s!zUq>l{yR& zrI{T~PYTqTdK0Ib+6(1aNf}CW&;O~4cKfHI+gXVbz)XG8yYsUmih5B6e+CYcXHLX{ z0|p1x>%HdgpoIxw*u6ogq&t4J58@?8^dC4xP_L)WT~_w^X?{3LMNPm=MQk;Xqp5j? zrN$X$P%qAVpLn12yRIrH7g~h?VyO$4UK@`mqc?i8Y(YC!_JBnY1wjDL=lW`UcI}=0 zU;gMF9M$srV(ZO8Q|AJRLjX16b2!Xri^-PHJ#j&Z!rhPF&wjW!oKBA~b`pt2r!l#9 zMTx=UWkk#2SeOGIVf3sx{O;?{MP~(zImHR(oPNPt3E)$*AxC$~YLeD(;5pcpg?#{c zf#0jO&%SRsSq>!sT?+Q^a89~N62NC!2E;})zVrfeW)7Tle*?#iOa)DDO56Yd002ov JPDHLkV1n-oc~}4d literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_hulk/data/mode_average.png b/cinelerra-5.1/plugins/theme_hulk/data/mode_average.png deleted file mode 100644 index 3edf8524135218ed830e1d7e3ad5d75f7ac7a161..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 840 zcmV-O1GoH%P)!Xy9y0_90WK~y-6os>;zT}2efe`n_0 zkG!OLCQ*!7sbUeN_(8QGl}a}%rKw0PZkj^VMaZJkg>+#>kh&2!6+zKODK11^X#};4 zMg$dYp$OU#7o|<5U#Lmjm*(Z(_wJqJ;=Z(rK@iVkhT+Wb{Qtw585tfP=6}V=$cW~7 z4wgox$bZF(Qd)&8%TmpFWZm4Jr_VHt1Q@Kh27217frZ@9{FMTUhS-V&A8rKHpx)ga zeQRwq_rTVNt{)ydw~VrC`gC&e{jUarSncicb4gqZsK8?Go4HFg?A`X~#`_m=`VSI# zc2h%~eDPENrP;W#7-I%F=#1(a8=8Imf&Ajt^vhGX6{d&=^tfFR(K%8mjA2LZq- z#-r==shRZH$zE0Y`a}=N`ny}*H9-^+3}l&YE2VQhQJn63p|Ru18)cA*@7J{2?!k5W zo8z--;_=#1Ca$(SAOryca31k-{SHopeemPUo}e z)eri!mY7*la_DH^<*RXJs!|T7c1yWjYKVB8KXkNyayn7Z=#IrS=E|HNc(?CbGeUgT zKEvBe+koKo?B!(gRAOdh&u9B~=5LHQto^IX#VqWe$xiSc@PXUhlM3L0JIBUKay_V5MJI@-t40DHnb%SZ3(B(>U*EN z->*2tV3~4Pw5n9tDl(kK;-GGcM=M?B0F~Y;oPf~#hO}K zwt|IVW`+TR3GCg@@Kb^#P2|RfhL8b@aD6^+eEZ43ecp1ijC_$+Mk}Xi0ccE;5~U<5 zaTh3;ev!6qrg~LpioyNIYhF4gSAPn&a+wjgqX^I>Nq|u64y%}d3vcGZd;d2uj59pP SC9Kf^0000?P)C-d?OQJ&LUtxJ6-CT>J@MfGE zUA=YTt@FMgj%fXfn5i#zc;kSjAg%ygB)yp>=Bd}4-~fY1<{!k7>Vv9Kw86-Hc-*>)HQj1A?8rkPq<o-I8v`Ob$js)fBn*SYU5acef`p}b^gP`NO$Fj&;dNcdMjOi`f$%-XDL~SJ8zB`1tDMoKoqB3 zIr%W&azwJ=Tq6qMD90Q?N5C7bNoS6gX Z+)woy?36)5Dv|&I002ovPDHLkV1h8`Kc@fy literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_hulk/data/mode_difference.png b/cinelerra-5.1/plugins/theme_hulk/data/mode_difference.png new file mode 100644 index 0000000000000000000000000000000000000000..c036b9d9555ef2e374470466b8e1aa5f33f69444 GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa&H|6fVg?3*gA5FU){JG5i7Y@t z_7YEDSM~>-(xQBt(_F4^0SayQba4#PIDdDNE!QCjf!6(Z*9dBRDn_$i(VOluG5U#s zr8nQk?GYEfbJCS>ED`8#a5>rEDwrhYxsv%Z&*#0B{A~aBAF=b?6Y*N|0i%$HZStSk zNjVJm*M8M#bg^YrKjX7$X*p_mIxl!#?&mw<4h2Q;y7fP1X)avH$iyn(HgSf?gJz!eHX6?-yk|@Ia^@>M)pTdT1e>U7$x{~FY@(xz5M4!)#=YM9Y Y{HHm)YU=)5K<6`fy85}Sb4q9e01l34$N&HU literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_hulk/data/mode_dodge.png b/cinelerra-5.1/plugins/theme_hulk/data/mode_dodge.png new file mode 100644 index 0000000000000000000000000000000000000000..68eed2ac21d5b799266d9e8eb1b83e245b7a4d8a GIT binary patch literal 895 zcmV-_1AzRAP)5zIo-g&I-8 zDE5mMD{Wevq$=rTl1w^p-n;L(m~n!LAYLxqb2#UJ&;R@n9GRJ!;eVak*;yCIF=#IE zBLAA#h?6i1+HUHlks9y4Q)TZRH(q<{taYv(4%j@m)BzNCMJMOWaf9-qXh0Z`GhvGf?bZ)qE=>7_T2*#ocH~;&@bY;}Rp}NY2qA`;@q7HaD>-b43B-g=+6KTIY)&yoxO^!* zu)oo$3l^^!OPaB7FuAniKKddLD5g+yO=%r)VKomb0_f0ves#$vy>eUX>xra^lsdJM znSpIz9@bXRHuUPWSy=&>Q$IgmfTFjClA)*u#qRj z6P;25nMkwaSBvhu+Tz8*o-TXraIIP206qgqvLMRk!@!K*t-&>YhHAb~Tj z=>SR60&50hUVeHVk>)+|Uis(~+0>Xmeqid==O@Fy@|o3gD+-mhK5h5x>)XlJguBJf z9obP*8E)HiNB*+Y4b5(CtZfK&z#&vO<3B!ozkA4POj75qA4a?<%g_u!4A$`M*o7!Z z*a41}(~{^k-~@h22VVL-Z>2TCe=Y@u7q9GXyLG}O2mlvF5s>8z*?(R@R@H*F_D>~p VM3jxg4JZHr002ovPDHLkV1gaJph*A# literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_hulk/data/mode_hardlight.png b/cinelerra-5.1/plugins/theme_hulk/data/mode_hardlight.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b9b64a4beb6a10d049d2d0e4830453c7db121f GIT binary patch literal 496 zcmV6wt|nKorNzTVxgdwpdzS2b6$4G zBJmQFGk+YmxV@R*eBUs4luRb^uSlg*%5fZk?SLk#Bu>`OYD#DJC%osPrmv#VS}SHG zVlP{Bm$v%!(z(O&YBIBOUfu5Qv1|2c1b|?mH=1ui*1s9(eF<8c06_piO((4F$P7RL z00kPz{*m%vNLU?>$!b1t`b$><07gQnrerznZW30NZ7m?}7T25G9g0L1_(%ErA)MQZ z*Vkn>ZZjLVJ`JR$S#b$wKLvm6cL)H3(W2jMou!l6ey(-C*;9dyrglGU_GZ?m&U2mG zpSF!|QsmRib;~fDw*N==ly%`_VLj$0(%CrEXw6AyE4!SU4-p7}0^#-Dc{)9wpO);v zEnx59O=}oac0>YFU~%|*b`n+yP`J7vm&X7o0&a?Z%V%Lp<$aT%$))>*cP+qj0|5Xk m7z_e1;YjO)OJ)g3DZc?!RgWV&+uq;+0000RO10Q`~#b`SU;jb3bH!e4L-M$;nCAXf!}GUM%vXux2b_ z)5LM?R2dywyfE?DI@d}6IrHoPF{ckdOBb)-duOly1{j5bzG}wRJu047Jgr>5zE!l@ z_Ne2RuMc@z_O!gFcPa2=0V4o{Si}`)M~br}h@@T^dxDrRy*N9HSd2v#FaY9VY;k4> zB2g^M|A``nu{p#Q#^wq~=E6vp>jDB&oY{%Vf&!^dOW$x9QCcAI<>FKWfZ>kX^Cv>! z>?J?&8ORGJlg14|Vu8{ko7dZm$DdPqo#t-edC@{wUQvGa`?)aiWnl><_@eFD0Qp`c zA{d8pRNqm3cmJ_2FP5m55QlNVs+_Gg$gSx@+ssejb_2d=kaThuV=;F1Dx1x@bd9mp zJ|JSP0I@nvH7fv(h`^VWA+>T%D$AxPBS^aliIbJfWPstmCh)PMh-s0CeNoaK+k=1a zhIHl0DAwPP3=j2To_Q2cH8w@RNdurZfYX>WBQY-q8(jr zh#)XE(WS{?xKI}AfJ0cSG(Oz?r+=H(1}8T0*MseGOp>4pfEcXdf5F8V{!c O0000v7zd@|cFu(0Z~zEnfB_H>rLi$^|4nbLM!tcu@+>My|2X-&r*0|a7%k5Nr~>SP(G|Yuu857+`Ul)#vb_hUi6k)WcbRDGzkTeXkcZHlO1~E`WLpA2&;ru zAPd4Oo8KPZsRh1NHb8%;qJ~s23}6!g&r@BU zY9~xGfR`sN$@uBS+}AUuHbw_Geq#m_L`0;}pr>B8?3QW{D(4xMxdYVe8Q3KtYV=wa zk#tN=w`Ps3`<+~xnr@w%Zp~If3#$(Tofp=zq@b#Uq2ealGl0&RS(t z2mynzu@$Ypf7NzcyNG(oh0007*Nkl=r?d%aMfkey$g|2D6NaOwpfTJ zCPXHgnfJYaP8XAzOyWko+{L};InTMzIrp9`>+9>h*Vx$DaCKdSmRS@z0v_CXbi(z^ zdtc1fAxaZWjM1rb^}_D=U;S3P(F}g|;x5{bu>uQv_TruSaQ|#A-M;@BU=&t*`}54L z|Gv{yrBs3iKzBB8&a3!vWw*$qfDr(h$HWFjR1b|JUZfcve0(eoRlop9HZunw1z@s%{DaS&Hr0EC;{j{SvUB&P)IYkSxZ<(2Jpp zvDeg>Q8$;1jiKMvjj;p8W(y+Yd?MQcM1w7(FH-8HSfLKE*}ioHRp;wdDOJAtz?g$f z()dl*ULB&-lb>x?gU#zko@**oYJnI#&RZ`}o&O2gdH!{Mu%=psuqu9tRHc0p)#)TL zg?h9a{BqNr)>MJIa&N)}vi7#v0Fq)S_S7+NX rxz94d6-5E0s-52X1G1_XthN6G0M0Q1Sc8`=00000NkvXXu0mjfIG$;V literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_pinklady/data/mode_and.png b/cinelerra-5.1/plugins/theme_pinklady/data/mode_and.png new file mode 100644 index 0000000000000000000000000000000000000000..dbbc4e204819fd377226bfbf91ae3a1e993dba69 GIT binary patch literal 831 zcmV-F1Hk-=P)cpdsS-JWs6;QEI7S>eDQKtdHl6`?(WVi0Mn zHgQzDw&VBwc87zT62zrqPBYs5=sP<*GqSzC&Hu8UogH5k1z0T!A}@#df$1!JWH4@oo^rX@9(W#**v;_^;z9l#A*>z;Ng?x^Do~8yumB&NzKo}FaX3I z%lcP0s7F2U&8>yj`^S?8FrBCM zR{!RYfFT}nsKX3U07+1Xdei}Xv;Ib}_Um42Hh0mO74FXNnrVA9<@8z;Ucfli6BdLD zvy;*ukMiL-5iv7~CaTtLGkj{qfI76cEQ$g|cT#yYvE&>gYb&mmj^5swET5#pdzXfj z$!Mb|s5f&+b|&qhH9IliFipXA_{+j*s!zUq>l{yR& zrI{T~PYTqTdK0Ib+6(1aNf}CW&;O~4cKfHI+gXVbz)XG8yYsUmih5B6e+CYcXHLX{ z0|p1x>%HdgpoIxw*u6ogq&t4J58@?8^dC4xP_L)WT~_w^X?{3LMNPm=MQk;Xqp5j? zrN$X$P%qAVpLn12yRIrH7g~h?VyO$4UK@`mqc?i8Y(YC!_JBnY1wjDL=lW`UcI}=0 zU;gMF9M$srV(ZO8Q|AJRLjX16b2!Xri^-PHJ#j&Z!rhPF&wjW!oKBA~b`pt2r!l#9 zMTx=UWkk#2SeOGIVf3sx{O;?{MP~(zImHR(oPNPt3E)$*AxC$~YLeD(;5pcpg?#{c zf#0jO&%SRsSq>!sT?+Q^a89~N62NC!2E;})zVrfeW)7Tle*?#iOa)DDO56Yd002ov JPDHLkV1n-oc~}4d literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_pinklady/data/mode_average.png b/cinelerra-5.1/plugins/theme_pinklady/data/mode_average.png deleted file mode 100644 index 3edf8524135218ed830e1d7e3ad5d75f7ac7a161..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 840 zcmV-O1GoH%P)!Xy9y0_90WK~y-6os>;zT}2efe`n_0 zkG!OLCQ*!7sbUeN_(8QGl}a}%rKw0PZkj^VMaZJkg>+#>kh&2!6+zKODK11^X#};4 zMg$dYp$OU#7o|<5U#Lmjm*(Z(_wJqJ;=Z(rK@iVkhT+Wb{Qtw585tfP=6}V=$cW~7 z4wgox$bZF(Qd)&8%TmpFWZm4Jr_VHt1Q@Kh27217frZ@9{FMTUhS-V&A8rKHpx)ga zeQRwq_rTVNt{)ydw~VrC`gC&e{jUarSncicb4gqZsK8?Go4HFg?A`X~#`_m=`VSI# zc2h%~eDPENrP;W#7-I%F=#1(a8=8Imf&Ajt^vhGX6{d&=^tfFR(K%8mjA2LZq- z#-r==shRZH$zE0Y`a}=N`ny}*H9-^+3}l&YE2VQhQJn63p|Ru18)cA*@7J{2?!k5W zo8z--;_=#1Ca$(SAOryca31k-{SHopeemPUo}e z)eri!mY7*la_DH^<*RXJs!|T7c1yWjYKVB8KXkNyayn7Z=#IrS=E|HNc(?CbGeUgT zKEvBe+koKo?B!(gRAOdh&u9B~=5LHQto^IX#VqWe$xiSc@PXUhlM3L0JIBUKay_V5MJI@-t40DHnb%SZ3(B(>U*EN z->*2tV3~4Pw5n9tDl(kK;-GGcM=M?B0F~Y;oPf~#hO}K zwt|IVW`+TR3GCg@@Kb^#P2|RfhL8b@aD6^+eEZ43ecp1ijC_$+Mk}Xi0ccE;5~U<5 zaTh3;ev!6qrg~LpioyNIYhF4gSAPn&a+wjgqX^I>Nq|u64y%}d3vcGZd;d2uj59pP SC9Kf^0000?P)C-d?OQJ&LUtxJ6-CT>J@MfGE zUA=YTt@FMgj%fXfn5i#zc;kSjAg%ygB)yp>=Bd}4-~fY1<{!k7>Vv9Kw86-Hc-*>)HQj1A?8rkPq<o-I8v`Ob$js)fBn*SYU5acef`p}b^gP`NO$Fj&;dNcdMjOi`f$%-XDL~SJ8zB`1tDMoKoqB3 zIr%W&azwJ=Tq6qMD90Q?N5C7bNoS6gX Z+)woy?36)5Dv|&I002ovPDHLkV1h8`Kc@fy literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_pinklady/data/mode_difference.png b/cinelerra-5.1/plugins/theme_pinklady/data/mode_difference.png new file mode 100644 index 0000000000000000000000000000000000000000..c036b9d9555ef2e374470466b8e1aa5f33f69444 GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa&H|6fVg?3*gA5FU){JG5i7Y@t z_7YEDSM~>-(xQBt(_F4^0SayQba4#PIDdDNE!QCjf!6(Z*9dBRDn_$i(VOluG5U#s zr8nQk?GYEfbJCS>ED`8#a5>rEDwrhYxsv%Z&*#0B{A~aBAF=b?6Y*N|0i%$HZStSk zNjVJm*M8M#bg^YrKjX7$X*p_mIxl!#?&mw<4h2Q;y7fP1X)avH$iyn(HgSf?gJz!eHX6?-yk|@Ia^@>M)pTdT1e>U7$x{~FY@(xz5M4!)#=YM9Y Y{HHm)YU=)5K<6`fy85}Sb4q9e01l34$N&HU literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_pinklady/data/mode_dodge.png b/cinelerra-5.1/plugins/theme_pinklady/data/mode_dodge.png new file mode 100644 index 0000000000000000000000000000000000000000..68eed2ac21d5b799266d9e8eb1b83e245b7a4d8a GIT binary patch literal 895 zcmV-_1AzRAP)5zIo-g&I-8 zDE5mMD{Wevq$=rTl1w^p-n;L(m~n!LAYLxqb2#UJ&;R@n9GRJ!;eVak*;yCIF=#IE zBLAA#h?6i1+HUHlks9y4Q)TZRH(q<{taYv(4%j@m)BzNCMJMOWaf9-qXh0Z`GhvGf?bZ)qE=>7_T2*#ocH~;&@bY;}Rp}NY2qA`;@q7HaD>-b43B-g=+6KTIY)&yoxO^!* zu)oo$3l^^!OPaB7FuAniKKddLD5g+yO=%r)VKomb0_f0ves#$vy>eUX>xra^lsdJM znSpIz9@bXRHuUPWSy=&>Q$IgmfTFjClA)*u#qRj z6P;25nMkwaSBvhu+Tz8*o-TXraIIP206qgqvLMRk!@!K*t-&>YhHAb~Tj z=>SR60&50hUVeHVk>)+|Uis(~+0>Xmeqid==O@Fy@|o3gD+-mhK5h5x>)XlJguBJf z9obP*8E)HiNB*+Y4b5(CtZfK&z#&vO<3B!ozkA4POj75qA4a?<%g_u!4A$`M*o7!Z z*a41}(~{^k-~@h22VVL-Z>2TCe=Y@u7q9GXyLG}O2mlvF5s>8z*?(R@R@H*F_D>~p VM3jxg4JZHr002ovPDHLkV1gaJph*A# literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_pinklady/data/mode_hardlight.png b/cinelerra-5.1/plugins/theme_pinklady/data/mode_hardlight.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b9b64a4beb6a10d049d2d0e4830453c7db121f GIT binary patch literal 496 zcmV6wt|nKorNzTVxgdwpdzS2b6$4G zBJmQFGk+YmxV@R*eBUs4luRb^uSlg*%5fZk?SLk#Bu>`OYD#DJC%osPrmv#VS}SHG zVlP{Bm$v%!(z(O&YBIBOUfu5Qv1|2c1b|?mH=1ui*1s9(eF<8c06_piO((4F$P7RL z00kPz{*m%vNLU?>$!b1t`b$><07gQnrerznZW30NZ7m?}7T25G9g0L1_(%ErA)MQZ z*Vkn>ZZjLVJ`JR$S#b$wKLvm6cL)H3(W2jMou!l6ey(-C*;9dyrglGU_GZ?m&U2mG zpSF!|QsmRib;~fDw*N==ly%`_VLj$0(%CrEXw6AyE4!SU4-p7}0^#-Dc{)9wpO);v zEnx59O=}oac0>YFU~%|*b`n+yP`J7vm&X7o0&a?Z%V%Lp<$aT%$))>*cP+qj0|5Xk m7z_e1;YjO)OJ)g3DZc?!RgWV&+uq;+0000RO10Q`~#b`SU;jb3bH!e4L-M$;nCAXf!}GUM%vXux2b_ z)5LM?R2dywyfE?DI@d}6IrHoPF{ckdOBb)-duOly1{j5bzG}wRJu047Jgr>5zE!l@ z_Ne2RuMc@z_O!gFcPa2=0V4o{Si}`)M~br}h@@T^dxDrRy*N9HSd2v#FaY9VY;k4> zB2g^M|A``nu{p#Q#^wq~=E6vp>jDB&oY{%Vf&!^dOW$x9QCcAI<>FKWfZ>kX^Cv>! z>?J?&8ORGJlg14|Vu8{ko7dZm$DdPqo#t-edC@{wUQvGa`?)aiWnl><_@eFD0Qp`c zA{d8pRNqm3cmJ_2FP5m55QlNVs+_Gg$gSx@+ssejb_2d=kaThuV=;F1Dx1x@bd9mp zJ|JSP0I@nvH7fv(h`^VWA+>T%D$AxPBS^aliIbJfWPstmCh)PMh-s0CeNoaK+k=1a zhIHl0DAwPP3=j2To_Q2cH8w@RNdurZfYX>WBQY-q8(jr zh#)XE(WS{?xKI}AfJ0cSG(Oz?r+=H(1}8T0*MseGOp>4pfEcXdf5F8V{!c O0000v7zd@|cFu(0Z~zEnfB_H>rLi$^|4nbLM!tcu@+>My|2X-&r*0|a7%k5Nr~>SP(G|Yuu857+`Ul)#vb_hUi6k)WcbRDGzkTeXkcZHlO1~E`WLpA2&;ru zAPd4Oo8KPZsRh1NHb8%;qJ~s23}6!g&r@BU zY9~xGfR`sN$@uBS+}AUuHbw_Geq#m_L`0;}pr>B8?3QW{D(4xMxdYVe8Q3KtYV=wa zk#tN=w`Ps3`<+~xnr@w%Zp~If3#$(Tofp=zq@b#Uq2ealGl0&RS(t z2mynzu@$Ypf7NzcyNG(oh0007*Nkl=r?d%aMfkey$g|2D6NaOwpfTJ zCPXHgnfJYaP8XAzOyWko+{L};InTMzIrp9`>+9>h*Vx$DaCKdSmRS@z0v_CXbi(z^ zdtc1fAxaZWjM1rb^}_D=U;S3P(F}g|;x5{bu>uQv_TruSaQ|#A-M;@BU=&t*`}54L z|Gv{yrBs3iKzBB8&a3!vWw*$qfDr(h$HWFjR1b|JUZfcve0(eoRlop9HZunw1z@s%{DaS&Hr0EC;{j{SvUB&P)IYkSxZ<(2Jpp zvDeg>Q8$;1jiKMvjj;p8W(y+Yd?MQcM1w7(FH-8HSfLKE*}ioHRp;wdDOJAtz?g$f z()dl*ULB&-lb>x?gU#zko@**oYJnI#&RZ`}o&O2gdH!{Mu%=psuqu9tRHc0p)#)TL zg?h9a{BqNr)>MJIa&N)}vi7#v0Fq)S_S7+NX rxz94d6-5E0s-52X1G1_XthN6G0M0Q1Sc8`=00000NkvXXu0mjfIG$;V literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_suv/data/mode_and.png b/cinelerra-5.1/plugins/theme_suv/data/mode_and.png new file mode 100644 index 0000000000000000000000000000000000000000..dbbc4e204819fd377226bfbf91ae3a1e993dba69 GIT binary patch literal 831 zcmV-F1Hk-=P)cpdsS-JWs6;QEI7S>eDQKtdHl6`?(WVi0Mn zHgQzDw&VBwc87zT62zrqPBYs5=sP<*GqSzC&Hu8UogH5k1z0T!A}@#df$1!JWH4@oo^rX@9(W#**v;_^;z9l#A*>z;Ng?x^Do~8yumB&NzKo}FaX3I z%lcP0s7F2U&8>yj`^S?8FrBCM zR{!RYfFT}nsKX3U07+1Xdei}Xv;Ib}_Um42Hh0mO74FXNnrVA9<@8z;Ucfli6BdLD zvy;*ukMiL-5iv7~CaTtLGkj{qfI76cEQ$g|cT#yYvE&>gYb&mmj^5swET5#pdzXfj z$!Mb|s5f&+b|&qhH9IliFipXA_{+j*s!zUq>l{yR& zrI{T~PYTqTdK0Ib+6(1aNf}CW&;O~4cKfHI+gXVbz)XG8yYsUmih5B6e+CYcXHLX{ z0|p1x>%HdgpoIxw*u6ogq&t4J58@?8^dC4xP_L)WT~_w^X?{3LMNPm=MQk;Xqp5j? zrN$X$P%qAVpLn12yRIrH7g~h?VyO$4UK@`mqc?i8Y(YC!_JBnY1wjDL=lW`UcI}=0 zU;gMF9M$srV(ZO8Q|AJRLjX16b2!Xri^-PHJ#j&Z!rhPF&wjW!oKBA~b`pt2r!l#9 zMTx=UWkk#2SeOGIVf3sx{O;?{MP~(zImHR(oPNPt3E)$*AxC$~YLeD(;5pcpg?#{c zf#0jO&%SRsSq>!sT?+Q^a89~N62NC!2E;})zVrfeW)7Tle*?#iOa)DDO56Yd002ov JPDHLkV1n-oc~}4d literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_suv/data/mode_average.png b/cinelerra-5.1/plugins/theme_suv/data/mode_average.png deleted file mode 100644 index 3edf8524135218ed830e1d7e3ad5d75f7ac7a161..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 840 zcmV-O1GoH%P)!Xy9y0_90WK~y-6os>;zT}2efe`n_0 zkG!OLCQ*!7sbUeN_(8QGl}a}%rKw0PZkj^VMaZJkg>+#>kh&2!6+zKODK11^X#};4 zMg$dYp$OU#7o|<5U#Lmjm*(Z(_wJqJ;=Z(rK@iVkhT+Wb{Qtw585tfP=6}V=$cW~7 z4wgox$bZF(Qd)&8%TmpFWZm4Jr_VHt1Q@Kh27217frZ@9{FMTUhS-V&A8rKHpx)ga zeQRwq_rTVNt{)ydw~VrC`gC&e{jUarSncicb4gqZsK8?Go4HFg?A`X~#`_m=`VSI# zc2h%~eDPENrP;W#7-I%F=#1(a8=8Imf&Ajt^vhGX6{d&=^tfFR(K%8mjA2LZq- z#-r==shRZH$zE0Y`a}=N`ny}*H9-^+3}l&YE2VQhQJn63p|Ru18)cA*@7J{2?!k5W zo8z--;_=#1Ca$(SAOryca31k-{SHopeemPUo}e z)eri!mY7*la_DH^<*RXJs!|T7c1yWjYKVB8KXkNyayn7Z=#IrS=E|HNc(?CbGeUgT zKEvBe+koKo?B!(gRAOdh&u9B~=5LHQto^IX#VqWe$xiSc@PXUhlM3L0JIBUKay_V5MJI@-t40DHnb%SZ3(B(>U*EN z->*2tV3~4Pw5n9tDl(kK;-GGcM=M?B0F~Y;oPf~#hO}K zwt|IVW`+TR3GCg@@Kb^#P2|RfhL8b@aD6^+eEZ43ecp1ijC_$+Mk}Xi0ccE;5~U<5 zaTh3;ev!6qrg~LpioyNIYhF4gSAPn&a+wjgqX^I>Nq|u64y%}d3vcGZd;d2uj59pP SC9Kf^0000?P)C-d?OQJ&LUtxJ6-CT>J@MfGE zUA=YTt@FMgj%fXfn5i#zc;kSjAg%ygB)yp>=Bd}4-~fY1<{!k7>Vv9Kw86-Hc-*>)HQj1A?8rkPq<o-I8v`Ob$js)fBn*SYU5acef`p}b^gP`NO$Fj&;dNcdMjOi`f$%-XDL~SJ8zB`1tDMoKoqB3 zIr%W&azwJ=Tq6qMD90Q?N5C7bNoS6gX Z+)woy?36)5Dv|&I002ovPDHLkV1h8`Kc@fy literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_suv/data/mode_difference.png b/cinelerra-5.1/plugins/theme_suv/data/mode_difference.png new file mode 100644 index 0000000000000000000000000000000000000000..c036b9d9555ef2e374470466b8e1aa5f33f69444 GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa&H|6fVg?3*gA5FU){JG5i7Y@t z_7YEDSM~>-(xQBt(_F4^0SayQba4#PIDdDNE!QCjf!6(Z*9dBRDn_$i(VOluG5U#s zr8nQk?GYEfbJCS>ED`8#a5>rEDwrhYxsv%Z&*#0B{A~aBAF=b?6Y*N|0i%$HZStSk zNjVJm*M8M#bg^YrKjX7$X*p_mIxl!#?&mw<4h2Q;y7fP1X)avH$iyn(HgSf?gJz!eHX6?-yk|@Ia^@>M)pTdT1e>U7$x{~FY@(xz5M4!)#=YM9Y Y{HHm)YU=)5K<6`fy85}Sb4q9e01l34$N&HU literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_suv/data/mode_dodge.png b/cinelerra-5.1/plugins/theme_suv/data/mode_dodge.png new file mode 100644 index 0000000000000000000000000000000000000000..68eed2ac21d5b799266d9e8eb1b83e245b7a4d8a GIT binary patch literal 895 zcmV-_1AzRAP)5zIo-g&I-8 zDE5mMD{Wevq$=rTl1w^p-n;L(m~n!LAYLxqb2#UJ&;R@n9GRJ!;eVak*;yCIF=#IE zBLAA#h?6i1+HUHlks9y4Q)TZRH(q<{taYv(4%j@m)BzNCMJMOWaf9-qXh0Z`GhvGf?bZ)qE=>7_T2*#ocH~;&@bY;}Rp}NY2qA`;@q7HaD>-b43B-g=+6KTIY)&yoxO^!* zu)oo$3l^^!OPaB7FuAniKKddLD5g+yO=%r)VKomb0_f0ves#$vy>eUX>xra^lsdJM znSpIz9@bXRHuUPWSy=&>Q$IgmfTFjClA)*u#qRj z6P;25nMkwaSBvhu+Tz8*o-TXraIIP206qgqvLMRk!@!K*t-&>YhHAb~Tj z=>SR60&50hUVeHVk>)+|Uis(~+0>Xmeqid==O@Fy@|o3gD+-mhK5h5x>)XlJguBJf z9obP*8E)HiNB*+Y4b5(CtZfK&z#&vO<3B!ozkA4POj75qA4a?<%g_u!4A$`M*o7!Z z*a41}(~{^k-~@h22VVL-Z>2TCe=Y@u7q9GXyLG}O2mlvF5s>8z*?(R@R@H*F_D>~p VM3jxg4JZHr002ovPDHLkV1gaJph*A# literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_suv/data/mode_hardlight.png b/cinelerra-5.1/plugins/theme_suv/data/mode_hardlight.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b9b64a4beb6a10d049d2d0e4830453c7db121f GIT binary patch literal 496 zcmV6wt|nKorNzTVxgdwpdzS2b6$4G zBJmQFGk+YmxV@R*eBUs4luRb^uSlg*%5fZk?SLk#Bu>`OYD#DJC%osPrmv#VS}SHG zVlP{Bm$v%!(z(O&YBIBOUfu5Qv1|2c1b|?mH=1ui*1s9(eF<8c06_piO((4F$P7RL z00kPz{*m%vNLU?>$!b1t`b$><07gQnrerznZW30NZ7m?}7T25G9g0L1_(%ErA)MQZ z*Vkn>ZZjLVJ`JR$S#b$wKLvm6cL)H3(W2jMou!l6ey(-C*;9dyrglGU_GZ?m&U2mG zpSF!|QsmRib;~fDw*N==ly%`_VLj$0(%CrEXw6AyE4!SU4-p7}0^#-Dc{)9wpO);v zEnx59O=}oac0>YFU~%|*b`n+yP`J7vm&X7o0&a?Z%V%Lp<$aT%$))>*cP+qj0|5Xk m7z_e1;YjO)OJ)g3DZc?!RgWV&+uq;+0000RO10Q`~#b`SU;jb3bH!e4L-M$;nCAXf!}GUM%vXux2b_ z)5LM?R2dywyfE?DI@d}6IrHoPF{ckdOBb)-duOly1{j5bzG}wRJu047Jgr>5zE!l@ z_Ne2RuMc@z_O!gFcPa2=0V4o{Si}`)M~br}h@@T^dxDrRy*N9HSd2v#FaY9VY;k4> zB2g^M|A``nu{p#Q#^wq~=E6vp>jDB&oY{%Vf&!^dOW$x9QCcAI<>FKWfZ>kX^Cv>! z>?J?&8ORGJlg14|Vu8{ko7dZm$DdPqo#t-edC@{wUQvGa`?)aiWnl><_@eFD0Qp`c zA{d8pRNqm3cmJ_2FP5m55QlNVs+_Gg$gSx@+ssejb_2d=kaThuV=;F1Dx1x@bd9mp zJ|JSP0I@nvH7fv(h`^VWA+>T%D$AxPBS^aliIbJfWPstmCh)PMh-s0CeNoaK+k=1a zhIHl0DAwPP3=j2To_Q2cH8w@RNdurZfYX>WBQY-q8(jr zh#)XE(WS{?xKI}AfJ0cSG(Oz?r+=H(1}8T0*MseGOp>4pfEcXdf5F8V{!c O0000v7zd@|cFu(0Z~zEnfB_H>rLi$^|4nbLM!tcu@+>My|2X-&r*0|a7%k5Nr~>SP(G|Yuu857+`Ul)#vb_hUi6k)WcbRDGzkTeXkcZHlO1~E`WLpA2&;ru zAPd4Oo8KPZsRh1NHb8%;qJ~s23}6!g&r@BU zY9~xGfR`sN$@uBS+}AUuHbw_Geq#m_L`0;}pr>B8?3QW{D(4xMxdYVe8Q3KtYV=wa zk#tN=w`Ps3`<+~xnr@w%Zp~If3#$(Tofp=zq@b#Uq2ealGl0&RS(t z2mynzu@$Ypf7NzcyNG(oh0007*Nkl=r?d%aMfkey$g|2D6NaOwpfTJ zCPXHgnfJYaP8XAzOyWko+{L};InTMzIrp9`>+9>h*Vx$DaCKdSmRS@z0v_CXbi(z^ zdtc1fAxaZWjM1rb^}_D=U;S3P(F}g|;x5{bu>uQv_TruSaQ|#A-M;@BU=&t*`}54L z|Gv{yrBs3iKzBB8&a3!vWw*$qfDr(h$HWFjR1b|JUZfcve0(eoRlop9HZunw1z@s%{DaS&Hr0EC;{j{SvUB&P)IYkSxZ<(2Jpp zvDeg>Q8$;1jiKMvjj;p8W(y+Yd?MQcM1w7(FH-8HSfLKE*}ioHRp;wdDOJAtz?g$f z()dl*ULB&-lb>x?gU#zko@**oYJnI#&RZ`}o&O2gdH!{Mu%=psuqu9tRHc0p)#)TL zg?h9a{BqNr)>MJIa&N)}vi7#v0Fq)S_S7+NX rxz94d6-5E0s-52X1G1_XthN6G0M0Q1Sc8`=00000NkvXXu0mjfIG$;V literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_unflat/data/mode_and.png b/cinelerra-5.1/plugins/theme_unflat/data/mode_and.png new file mode 100644 index 0000000000000000000000000000000000000000..dbbc4e204819fd377226bfbf91ae3a1e993dba69 GIT binary patch literal 831 zcmV-F1Hk-=P)cpdsS-JWs6;QEI7S>eDQKtdHl6`?(WVi0Mn zHgQzDw&VBwc87zT62zrqPBYs5=sP<*GqSzC&Hu8UogH5k1z0T!A}@#df$1!JWH4@oo^rX@9(W#**v;_^;z9l#A*>z;Ng?x^Do~8yumB&NzKo}FaX3I z%lcP0s7F2U&8>yj`^S?8FrBCM zR{!RYfFT}nsKX3U07+1Xdei}Xv;Ib}_Um42Hh0mO74FXNnrVA9<@8z;Ucfli6BdLD zvy;*ukMiL-5iv7~CaTtLGkj{qfI76cEQ$g|cT#yYvE&>gYb&mmj^5swET5#pdzXfj z$!Mb|s5f&+b|&qhH9IliFipXA_{+j*s!zUq>l{yR& zrI{T~PYTqTdK0Ib+6(1aNf}CW&;O~4cKfHI+gXVbz)XG8yYsUmih5B6e+CYcXHLX{ z0|p1x>%HdgpoIxw*u6ogq&t4J58@?8^dC4xP_L)WT~_w^X?{3LMNPm=MQk;Xqp5j? zrN$X$P%qAVpLn12yRIrH7g~h?VyO$4UK@`mqc?i8Y(YC!_JBnY1wjDL=lW`UcI}=0 zU;gMF9M$srV(ZO8Q|AJRLjX16b2!Xri^-PHJ#j&Z!rhPF&wjW!oKBA~b`pt2r!l#9 zMTx=UWkk#2SeOGIVf3sx{O;?{MP~(zImHR(oPNPt3E)$*AxC$~YLeD(;5pcpg?#{c zf#0jO&%SRsSq>!sT?+Q^a89~N62NC!2E;})zVrfeW)7Tle*?#iOa)DDO56Yd002ov JPDHLkV1n-oc~}4d literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_unflat/data/mode_average.png b/cinelerra-5.1/plugins/theme_unflat/data/mode_average.png deleted file mode 100644 index 3edf8524135218ed830e1d7e3ad5d75f7ac7a161..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 840 zcmV-O1GoH%P)!Xy9y0_90WK~y-6os>;zT}2efe`n_0 zkG!OLCQ*!7sbUeN_(8QGl}a}%rKw0PZkj^VMaZJkg>+#>kh&2!6+zKODK11^X#};4 zMg$dYp$OU#7o|<5U#Lmjm*(Z(_wJqJ;=Z(rK@iVkhT+Wb{Qtw585tfP=6}V=$cW~7 z4wgox$bZF(Qd)&8%TmpFWZm4Jr_VHt1Q@Kh27217frZ@9{FMTUhS-V&A8rKHpx)ga zeQRwq_rTVNt{)ydw~VrC`gC&e{jUarSncicb4gqZsK8?Go4HFg?A`X~#`_m=`VSI# zc2h%~eDPENrP;W#7-I%F=#1(a8=8Imf&Ajt^vhGX6{d&=^tfFR(K%8mjA2LZq- z#-r==shRZH$zE0Y`a}=N`ny}*H9-^+3}l&YE2VQhQJn63p|Ru18)cA*@7J{2?!k5W zo8z--;_=#1Ca$(SAOryca31k-{SHopeemPUo}e z)eri!mY7*la_DH^<*RXJs!|T7c1yWjYKVB8KXkNyayn7Z=#IrS=E|HNc(?CbGeUgT zKEvBe+koKo?B!(gRAOdh&u9B~=5LHQto^IX#VqWe$xiSc@PXUhlM3L0JIBUKay_V5MJI@-t40DHnb%SZ3(B(>U*EN z->*2tV3~4Pw5n9tDl(kK;-GGcM=M?B0F~Y;oPf~#hO}K zwt|IVW`+TR3GCg@@Kb^#P2|RfhL8b@aD6^+eEZ43ecp1ijC_$+Mk}Xi0ccE;5~U<5 zaTh3;ev!6qrg~LpioyNIYhF4gSAPn&a+wjgqX^I>Nq|u64y%}d3vcGZd;d2uj59pP SC9Kf^0000?P)C-d?OQJ&LUtxJ6-CT>J@MfGE zUA=YTt@FMgj%fXfn5i#zc;kSjAg%ygB)yp>=Bd}4-~fY1<{!k7>Vv9Kw86-Hc-*>)HQj1A?8rkPq<o-I8v`Ob$js)fBn*SYU5acef`p}b^gP`NO$Fj&;dNcdMjOi`f$%-XDL~SJ8zB`1tDMoKoqB3 zIr%W&azwJ=Tq6qMD90Q?N5C7bNoS6gX Z+)woy?36)5Dv|&I002ovPDHLkV1h8`Kc@fy literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_unflat/data/mode_difference.png b/cinelerra-5.1/plugins/theme_unflat/data/mode_difference.png new file mode 100644 index 0000000000000000000000000000000000000000..c036b9d9555ef2e374470466b8e1aa5f33f69444 GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa&H|6fVg?3*gA5FU){JG5i7Y@t z_7YEDSM~>-(xQBt(_F4^0SayQba4#PIDdDNE!QCjf!6(Z*9dBRDn_$i(VOluG5U#s zr8nQk?GYEfbJCS>ED`8#a5>rEDwrhYxsv%Z&*#0B{A~aBAF=b?6Y*N|0i%$HZStSk zNjVJm*M8M#bg^YrKjX7$X*p_mIxl!#?&mw<4h2Q;y7fP1X)avH$iyn(HgSf?gJz!eHX6?-yk|@Ia^@>M)pTdT1e>U7$x{~FY@(xz5M4!)#=YM9Y Y{HHm)YU=)5K<6`fy85}Sb4q9e01l34$N&HU literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_unflat/data/mode_dodge.png b/cinelerra-5.1/plugins/theme_unflat/data/mode_dodge.png new file mode 100644 index 0000000000000000000000000000000000000000..68eed2ac21d5b799266d9e8eb1b83e245b7a4d8a GIT binary patch literal 895 zcmV-_1AzRAP)5zIo-g&I-8 zDE5mMD{Wevq$=rTl1w^p-n;L(m~n!LAYLxqb2#UJ&;R@n9GRJ!;eVak*;yCIF=#IE zBLAA#h?6i1+HUHlks9y4Q)TZRH(q<{taYv(4%j@m)BzNCMJMOWaf9-qXh0Z`GhvGf?bZ)qE=>7_T2*#ocH~;&@bY;}Rp}NY2qA`;@q7HaD>-b43B-g=+6KTIY)&yoxO^!* zu)oo$3l^^!OPaB7FuAniKKddLD5g+yO=%r)VKomb0_f0ves#$vy>eUX>xra^lsdJM znSpIz9@bXRHuUPWSy=&>Q$IgmfTFjClA)*u#qRj z6P;25nMkwaSBvhu+Tz8*o-TXraIIP206qgqvLMRk!@!K*t-&>YhHAb~Tj z=>SR60&50hUVeHVk>)+|Uis(~+0>Xmeqid==O@Fy@|o3gD+-mhK5h5x>)XlJguBJf z9obP*8E)HiNB*+Y4b5(CtZfK&z#&vO<3B!ozkA4POj75qA4a?<%g_u!4A$`M*o7!Z z*a41}(~{^k-~@h22VVL-Z>2TCe=Y@u7q9GXyLG}O2mlvF5s>8z*?(R@R@H*F_D>~p VM3jxg4JZHr002ovPDHLkV1gaJph*A# literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/theme_unflat/data/mode_hardlight.png b/cinelerra-5.1/plugins/theme_unflat/data/mode_hardlight.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b9b64a4beb6a10d049d2d0e4830453c7db121f GIT binary patch literal 496 zcmV6wt|nKorNzTVxgdwpdzS2b6$4G zBJmQFGk+YmxV@R*eBUs4luRb^uSlg*%5fZk?SLk#Bu>`OYD#DJC%osPrmv#VS}SHG zVlP{Bm$v%!(z(O&YBIBOUfu5Qv1|2c1b|?mH=1ui*1s9(eF<8c06_piO((4F$P7RL z00kPz{*m%vNLU?>$!b1t`b$><07gQnrerznZW30NZ7m?}7T25G9g0L1_(%ErA)MQZ z*Vkn>ZZjLVJ`JR$S#b$wKLvm6cL)H3(W2jMou!l6ey(-C*;9dyrglGU_GZ?m&U2mG zpSF!|QsmRib;~fDw*N==ly%`_VLj$0(%CrEXw6AyE4!SU4-p7}0^#-Dc{)9wpO);v zEnx59O=}oac0>YFU~%|*b`n+yP`J7vm&X7o0&a?Z%V%Lp<$aT%$))>*cP+qj0|5Xk m7z_e1;YjO)OJ)g3DZc?!RgWV&+uq;+0000RO10Q`~#b`SU;jb3bH!e4L-M$;nCAXf!}GUM%vXux2b_ z)5LM?R2dywyfE?DI@d}6IrHoPF{ckdOBb)-duOly1{j5bzG}wRJu047Jgr>5zE!l@ z_Ne2RuMc@z_O!gFcPa2=0V4o{Si}`)M~br}h@@T^dxDrRy*N9HSd2v#FaY9VY;k4> zB2g^M|A``nu{p#Q#^wq~=E6vp>jDB&oY{%Vf&!^dOW$x9QCcAI<>FKWfZ>kX^Cv>! z>?J?&8ORGJlg14|Vu8{ko7dZm$DdPqo#t-edC@{wUQvGa`?)aiWnl><_@eFD0Qp`c zA{d8pRNqm3cmJ_2FP5m55QlNVs+_Gg$gSx@+ssejb_2d=kaThuV=;F1Dx1x@bd9mp zJ|JSP0I@nvH7fv(h`^VWA+>T%D$AxPBS^aliIbJfWPstmCh)PMh-s0CeNoaK+k=1a zhIHl0DAwPP3=j2To_Q2cH8w@RNdurZfYX>WBQY-q8(jr zh#)XE(WS{?xKI}AfJ0cSG(Oz?r+=H(1}8T0*MseGOp>4pfEcXdf5F8V{!c O0000v7zd@|cFu(0Z~zEnfB_H>rLi$^|4nbLM!tcu@+>My|2X-&r*0|a7%k5Nr~>SP(G|Yuu857+`Ul)#vb_hUi6k)WcbRDGzkTeXkcZHlO1~E`WLpA2&;ru zAPd4Oo8KPZsRh1NHb8%;qJ~s23}6!g&r@BU zY9~xGfR`sN$@uBS+}AUuHbw_Geq#m_L`0;}pr>B8?3QW{D(4xMxdYVe8Q3KtYV=wa zk#tN=w`Ps3`<+~xnr@w%Zp~If3#$(Tofp=zq@b#Uq2ealGl0&RS(t z2mynzu@$Ypf7NzcyNG(oh0007*Nkl=r?d%aMfkey$g|2D6NaOwpfTJ zCPXHgnfJYaP8XAzOyWko+{L};InTMzIrp9`>+9>h*Vx$DaCKdSmRS@z0v_CXbi(z^ zdtc1fAxaZWjM1rb^}_D=U;S3P(F}g|;x5{bu>uQv_TruSaQ|#A-M;@BU=&t*`}54L z|Gv{yrBs3iKzBB8&a3!vWw*$qfDr(h$HWFjR1b|JUZfcve0(eoRlop9HZunw1z@s%{DaS&Hr0EC;{j{SvUB&P)IYkSxZ<(2Jpp zvDeg>Q8$;1jiKMvjj;p8W(y+Yd?MQcM1w7(FH-8HSfLKE*}ioHRp;wdDOJAtz?g$f z()dl*ULB&-lb>x?gU#zko@**oYJnI#&RZ`}o&O2gdH!{Mu%=psuqu9tRHc0p)#)TL zg?h9a{BqNr)>MJIa&N)}vi7#v0Fq)S_S7+NX rxz94d6-5E0s-52X1G1_XthN6G0M0Q1Sc8`=00000NkvXXu0mjfIG$;V literal 0 HcmV?d00001 -- 2.26.2