graphic art overlay modes, pref window resize, submenu fixes
[goodguy/history.git] / cinelerra-5.1 / cinelerra / overlaynearest.C
diff --git a/cinelerra-5.1/cinelerra/overlaynearest.C b/cinelerra-5.1/cinelerra/overlaynearest.C
new file mode 100644 (file)
index 0000000..e4a842d
--- /dev/null
@@ -0,0 +1,195 @@
+#include "overlayframe.h"
+
+/* Nearest Neighbor scale / translate / blend ********************/
+
+#define XBLEND_3NN(FN, temp_type, type, max, components, ofs, round) { \
+       temp_type opcty = fade * max + round, trnsp = max - opcty; \
+       type** output_rows = (type**)output->get_rows(); \
+       type** input_rows = (type**)input->get_rows(); \
+       ox *= components; \
+ \
+       for(int i = pkg->out_row1; i < pkg->out_row2; i++) { \
+               int *lx = engine->in_lookup_x; \
+               type* in_row = input_rows[*ly++]; \
+               type* output = output_rows[i] + ox; \
+               for(int j = 0; j < ow; j++) { \
+                       in_row += *lx++; \
+                       if( components == 4 ) { \
+                               temp_type r, g, b, a; \
+                               ALPHA4_BLEND(FN, temp_type, in_row, output, max, ofs, ofs, round); \
+                               ALPHA4_STORE(output, ofs, max); \
+                       } \
+                       else { \
+                               temp_type r, g, b; \
+                               ALPHA3_BLEND(FN, temp_type, in_row, output, max, ofs, ofs, round); \
+                               ALPHA3_STORE(output, ofs, max); \
+                       } \
+                       output += components; \
+               } \
+       } \
+       break; \
+}
+
+#define XBLEND_NN(FN) { \
+       switch(input->get_color_model()) { \
+       case BC_RGB_FLOAT:      XBLEND_3NN(FN, z_float,   z_float,    1.f,    3, 0,       0.f); \
+       case BC_RGBA_FLOAT:     XBLEND_3NN(FN, z_float,   z_float,    1.f,    4, 0,       0.f); \
+       case BC_RGB888:         XBLEND_3NN(FN, z_int32_t, z_uint8_t,  0xff,   3, 0,      .5f); \
+       case BC_YUV888:         XBLEND_3NN(FN, z_int32_t, z_uint8_t,  0xff,   3, 0x80,   .5f); \
+       case BC_RGBA8888:       XBLEND_3NN(FN, z_int32_t, z_uint8_t,  0xff,   4, 0,      .5f); \
+       case BC_YUVA8888:       XBLEND_3NN(FN, z_int32_t, z_uint8_t,  0xff,   4, 0x80,   .5f); \
+       case BC_RGB161616:      XBLEND_3NN(FN, z_int64_t, z_uint16_t, 0xffff, 3, 0,      .5f); \
+       case BC_YUV161616:      XBLEND_3NN(FN, z_int64_t, z_uint16_t, 0xffff, 3, 0x8000, .5f); \
+       case BC_RGBA16161616:   XBLEND_3NN(FN, z_int64_t, z_uint16_t, 0xffff, 4, 0,      .5f); \
+       case BC_YUVA16161616:   XBLEND_3NN(FN, z_int64_t, z_uint16_t, 0xffff, 4, 0x8000, .5f); \
+       } \
+       break; \
+}
+
+NNPackage::NNPackage()
+{
+}
+
+NNUnit::NNUnit(NNEngine *server)
+ : LoadClient(server)
+{
+       this->engine = server;
+}
+
+NNUnit::~NNUnit()
+{
+}
+
+void NNUnit::process_package(LoadPackage *package)
+{
+       NNPackage *pkg = (NNPackage*)package;
+       VFrame *output = engine->output;
+       VFrame *input = engine->input;
+       int mode = engine->mode;
+       float fade =
+               BC_CModels::has_alpha(input->get_color_model()) &&
+               mode == TRANSFER_REPLACE ? 1.f : engine->alpha;
+
+       int ox = engine->out_x1i;
+       int ow = engine->out_x2i - ox;
+       int *ly = engine->in_lookup_y + pkg->out_row1;
+
+       BLEND_SWITCH(XBLEND_NN);
+}
+
+NNEngine::NNEngine(int cpus)
+ : LoadServer(cpus, cpus)
+{
+       in_lookup_x = 0;
+       in_lookup_y = 0;
+}
+
+NNEngine::~NNEngine()
+{
+       if(in_lookup_x)
+               delete[] in_lookup_x;
+       if(in_lookup_y)
+               delete[] in_lookup_y;
+}
+
+void NNEngine::init_packages()
+{
+       int in_w = input->get_w();
+       int in_h = input->get_h();
+       int out_w = output->get_w();
+       int out_h = output->get_h();
+
+       float in_subw = in_x2 - in_x1;
+       float in_subh = in_y2 - in_y1;
+       float out_subw = out_x2 - out_x1;
+       float out_subh = out_y2 - out_y1;
+       int first, last, count, i;
+       int components = 3;
+
+       out_x1i = rint(out_x1);
+       out_x2i = rint(out_x2);
+       if(out_x1i < 0) out_x1i = 0;
+       if(out_x1i > out_w) out_x1i = out_w;
+       if(out_x2i < 0) out_x2i = 0;
+       if(out_x2i > out_w) out_x2i = out_w;
+       int out_wi = out_x2i - out_x1i;
+       if( !out_wi ) return;
+
+       delete[] in_lookup_x;
+       in_lookup_x = new int[out_wi];
+       delete[] in_lookup_y;
+       in_lookup_y = new int[out_h];
+
+       switch(input->get_color_model()) {
+       case BC_RGBA_FLOAT:
+       case BC_RGBA8888:
+       case BC_YUVA8888:
+       case BC_RGBA16161616:
+               components = 4;
+               break;
+       }
+
+       first = count = 0;
+
+       for(i = out_x1i; i < out_x2i; i++) {
+               int in = (i - out_x1 + .5) * in_subw / out_subw + in_x1;
+               if(in < in_x1)
+                       in = in_x1;
+               if(in > in_x2)
+                       in = in_x2;
+
+               if(in >= 0 && in < in_w && in >= in_x1 && i >= 0 && i < out_w) {
+                       if(count == 0) {
+                               first = i;
+                               in_lookup_x[0] = in * components;
+                       }
+                       else {
+                               in_lookup_x[count] = (in-last)*components;
+                       }
+                       last = in;
+                       count++;
+               }
+               else if(count)
+                       break;
+       }
+       out_x1i = first;
+       out_x2i = first + count;
+       first = count = 0;
+
+       for(i = out_y1; i < out_y2; i++) {
+               int in = (i - out_y1+.5) * in_subh / out_subh + in_y1;
+               if(in < in_y1) in = in_y1;
+               if(in > in_y2) in = in_y2;
+               if(in >= 0 && in < in_h && i >= 0 && i < out_h) {
+                       if(count == 0) first = i;
+                       in_lookup_y[i] = in;
+                       count++;
+               }
+               else if(count)
+                       break;
+       }
+       out_y1 = first;
+       out_y2 = first + count;
+
+       int rows = count;
+       int pkgs = get_total_packages();
+       int row1 = out_y1, row2 = row1;
+       for(int i = 0; i < pkgs; row1=row2 ) {
+               NNPackage *package = (NNPackage*)get_package(i);
+               row2 = ++i * rows / pkgs + out_y1;
+               package->out_row1 = row1;
+               package->out_row2 = row2;
+       }
+}
+
+LoadClient* NNEngine::new_client()
+{
+       return new NNUnit(this);
+}
+
+LoadPackage* NNEngine::new_package()
+{
+       return new NNPackage;
+}
+
+