$(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 \
--- /dev/null
+#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;
+}
+
+
*
*/
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-
#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
* 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;
}
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;
-}
+++ /dev/null
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-
-#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()
-{
-}
-
-
+++ /dev/null
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-
-#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()
-{
-}
-
-
+++ /dev/null
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-
-#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()
-{
-}
-
-
+++ /dev/null
-#include <math.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-
-#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()
-{
-}
-
-
#include "loadbalance.h"
#include "overlayframe.inc"
-#include "vframe.inc"
+#include "vframe.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
#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:
+++ /dev/null
-#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
+++ /dev/null
-#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
+++ /dev/null
-#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
+++ /dev/null
-#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
// 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
#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
--- /dev/null
+#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;
+}
+
+
--- /dev/null
+#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;
+}
+
+
"mode_replace",
"mode_max",
"mode_min",
- "mode_average",
"mode_darken",
"mode_lighten",
"mode_dst",
"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<TRANSFER_TYPES; ++mode ) {
mode_icons[mode] = new BC_Pixmap(this,
#include "maskauto.h"
#include "mutex.h"
#include "overlayframe.inc"
+#include "overlayframe.h"
#include "playback3d.h"
#include "pluginclient.h"
#include "pluginvclient.h"
#include <unistd.h>
#include <fcntl.h>
+#define QQ(q)#q
+#define SS(s)QQ(s)
// Shaders
" 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"
" 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"
// 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");
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;
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");
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");
void VModePatch::create_objects()
{
- for( int mode=0; mode<TRANSFER_TYPES; ++mode )
- add_item(new VModePatchItem(this, mode_to_text(mode), mode));
+ VModePatchItem *mode_item;
+ VModePatchSubMenu *submenu;
+ add_item(mode_item = new VModePatchItem(this, mode_to_text(TRANSFER_NORMAL), TRANSFER_NORMAL));
+ add_item(mode_item = new VModePatchItem(this, _("Arithmetic..."), -1));
+ mode_item->add_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)
{
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; j<n; ++j ) {
+ VModePatchItem *subitem = (VModePatchItem*)submenu->get_item(j);
+ subitem->set_checked(subitem->mode == 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");
}
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();
#ifndef VPATCHGUI_H
#define VPATCHGUI_H
+#include "bcmenuitem.h"
+#include "bcmenupopup.h"
#include "floatauto.inc"
#include "guicast.h"
#include "patchgui.h"
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:
{
submenu->deactivate_submenus(exclude);
submenu->deactivate_menu();
+ submenu->popup_menu = 0;
highlighted = 0;
}
return 0;
&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;
}
return 0;
}
+BC_SubMenu* BC_MenuItem::get_submenu()
+{
+ return submenu;
+}
+
char* BC_MenuItem::get_text()
{
return text;
int draw();
BC_WindowBase* get_top_level();
BC_PopupMenu* get_popup_menu();
+ BC_SubMenu *get_submenu();
private:
BC_WindowBase *top_level;
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; i<menu_items.size(); ++i ) {
+ if( !menu_items[i]->submenu ) continue;
+ if( menu_items[i]->submenu->cursor_inside() ) return 1;
+ }
+ return 0;
}
int BC_MenuPopup::get_w()
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;
}
#include "language.h"
#include "overlayframe.h"
#include "pluginvclient.h"
+#include "vpatchgui.h"
#include "vframe.h"
#include <string.h>
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)
" 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);