Merge CV, ver=5.1; ops/methods from HV, and interface from CV where possible
[goodguy/history.git] / cinelerra-5.1 / plugins / flip / flip.C
diff --git a/cinelerra-5.1/plugins/flip/flip.C b/cinelerra-5.1/plugins/flip/flip.C
new file mode 100644 (file)
index 0000000..6c27e8a
--- /dev/null
@@ -0,0 +1,332 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "clip.h"
+#include "bccmodels.h"
+#include "bchash.h"
+#include "filexml.h"
+#include "flip.h"
+#include "flipwindow.h"
+#include "language.h"
+
+#include <stdint.h>
+#include <string.h>
+
+REGISTER_PLUGIN(FlipMain)
+
+
+
+
+
+
+FlipConfig::FlipConfig()
+{
+       flip_horizontal = 0;
+       flip_vertical = 0;
+}
+
+void FlipConfig::copy_from(FlipConfig &that)
+{
+       flip_horizontal = that.flip_horizontal;
+       flip_vertical = that.flip_vertical;
+}
+
+int FlipConfig::equivalent(FlipConfig &that)
+{
+       return flip_horizontal == that.flip_horizontal &&
+               flip_vertical == that.flip_vertical;
+}
+
+void FlipConfig::interpolate(FlipConfig &prev, 
+       FlipConfig &next, 
+       long prev_frame, 
+       long next_frame, 
+       long current_frame)
+{
+       this->flip_horizontal = prev.flip_horizontal;
+       this->flip_vertical = prev.flip_vertical;
+}
+
+
+
+
+
+
+
+
+
+
+FlipMain::FlipMain(PluginServer *server)
+ : PluginVClient(server)
+{
+       
+}
+
+FlipMain::~FlipMain()
+{
+       
+}
+
+const char* FlipMain::plugin_title() { return _("Flip"); }
+int FlipMain::is_realtime() { return 1; }
+       
+
+#define SWAP_PIXELS(type, components, in, out) \
+{ \
+       type temp = in[0]; \
+       in[0] = out[0]; \
+       out[0] = temp; \
+ \
+       temp = in[1]; \
+       in[1] = out[1]; \
+       out[1] = temp; \
+ \
+       temp = in[2]; \
+       in[2] = out[2]; \
+       out[2] = temp; \
+ \
+       if(components == 4) \
+       { \
+               temp = in[3]; \
+               in[3] = out[3]; \
+               out[3] = temp; \
+       } \
+}
+
+#define FLIP_MACRO(type, components) \
+{ \
+       type **input_rows, **output_rows; \
+       type *input_row, *output_row; \
+       input_rows = ((type**)frame->get_rows()); \
+       output_rows = ((type**)frame->get_rows()); \
+ \
+       if(config.flip_vertical) \
+       { \
+               for(i = 0, j = h - 1; i < h / 2; i++, j--) \
+               { \
+                       input_row = input_rows[i]; \
+                       output_row = output_rows[j]; \
+                       for(k = 0; k < w; k++) \
+                       { \
+                               SWAP_PIXELS(type, components, output_row, input_row); \
+                               output_row += components; \
+                               input_row += components; \
+                       } \
+               } \
+       } \
+ \
+       if(config.flip_horizontal) \
+       { \
+               for(i = 0; i < h; i++) \
+               { \
+                       input_row = input_rows[i]; \
+                       output_row = output_rows[i] + (w - 1) * components; \
+                       for(k = 0; k < w / 2; k++) \
+                       { \
+                               SWAP_PIXELS(type, components, output_row, input_row); \
+                               input_row += components; \
+                               output_row -= components; \
+                       } \
+               } \
+       } \
+}
+
+int FlipMain::process_buffer(VFrame *frame,
+               int64_t start_position,
+               double frame_rate)
+{
+       int i, j, k;
+       int w = frame->get_w();
+       int h = frame->get_h();
+       int colormodel = frame->get_color_model();
+
+       load_configuration();
+
+       read_frame(frame,
+               0,
+               get_source_position(),
+               get_framerate(),
+               get_use_opengl());
+
+
+
+       if(get_use_opengl()) 
+       {
+               if(config.flip_vertical || config.flip_horizontal)
+                       return run_opengl();
+               else
+                       return 0;
+       }
+
+       switch(colormodel)
+       {
+               case BC_RGB888:
+               case BC_YUV888:
+                       FLIP_MACRO(unsigned char, 3);
+                       break;
+               case BC_RGB_FLOAT:
+                       FLIP_MACRO(float, 3);
+                       break;
+               case BC_RGB161616:
+               case BC_YUV161616:
+                       FLIP_MACRO(uint16_t, 3);
+                       break;
+               case BC_RGBA8888:
+               case BC_YUVA8888:
+                       FLIP_MACRO(unsigned char, 4);
+                       break;
+               case BC_RGBA_FLOAT:
+                       FLIP_MACRO(float, 4);
+                       break;
+               case BC_RGBA16161616:
+               case BC_YUVA16161616:
+                       FLIP_MACRO(uint16_t, 4);
+                       break;
+       }
+       return 0;
+}
+
+
+NEW_WINDOW_MACRO(FlipMain, FlipWindow)
+LOAD_CONFIGURATION_MACRO(FlipMain, FlipConfig)
+
+void FlipMain::update_gui()
+{
+       if(thread)
+       {
+               load_configuration();
+               thread->window->lock_window();
+               ((FlipWindow*)thread->window)->flip_vertical->update((int)config.flip_vertical);
+               ((FlipWindow*)thread->window)->flip_horizontal->update((int)config.flip_horizontal);
+               thread->window->unlock_window();
+       }
+}
+
+void FlipMain::save_data(KeyFrame *keyframe)
+{
+       FileXML output;
+
+// cause data to be stored directly in text
+       output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
+       output.tag.set_title("FLIP");
+       output.append_tag();
+       if(config.flip_vertical)
+       {
+               output.tag.set_title("VERTICAL");
+               output.append_tag();
+               output.tag.set_title("/VERTICAL");
+               output.append_tag();
+       }
+
+       if(config.flip_horizontal)
+       {       
+               output.tag.set_title("HORIZONTAL");
+               output.append_tag();
+               output.tag.set_title("/HORIZONTAL");
+               output.append_tag();
+       }
+       output.tag.set_title("/FLIP");
+       output.append_tag();
+       output.append_newline();
+       output.terminate_string();
+// data is now in *text
+}
+
+void FlipMain::read_data(KeyFrame *keyframe)
+{
+       FileXML input;
+
+       input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
+
+       int result = 0;
+       config.flip_vertical = config.flip_horizontal = 0;
+
+       while(!result)
+       {
+               result = input.read_tag();
+
+               if(!result)
+               {
+                       if(input.tag.title_is("VERTICAL"))
+                       {
+                               config.flip_vertical = 1;
+                       }
+                       else
+                       if(input.tag.title_is("HORIZONTAL"))
+                       {
+                               config.flip_horizontal = 1;
+                       }
+               }
+       }
+}
+
+
+int FlipMain::handle_opengl()
+{
+#ifdef HAVE_GL
+       get_output()->to_texture();
+       get_output()->enable_opengl();
+       get_output()->init_screen();
+       get_output()->bind_texture(0);
+
+       if(config.flip_vertical && !config.flip_horizontal)
+       {
+               get_output()->draw_texture(0,
+                       0,
+                       get_output()->get_w(),
+                       get_output()->get_h(),
+                       0,
+                       get_output()->get_h(),
+                       get_output()->get_w(),
+                       0);
+       }
+
+       if(config.flip_horizontal && !config.flip_vertical)
+       {
+               get_output()->draw_texture(0,
+                       0,
+                       get_output()->get_w(),
+                       get_output()->get_h(),
+                       get_output()->get_w(),
+                       0,
+                       0,
+                       get_output()->get_h());
+       }
+
+       if(config.flip_vertical && config.flip_horizontal)
+       {
+               get_output()->draw_texture(0,
+                       0,
+                       get_output()->get_w(),
+                       get_output()->get_h(),
+                       get_output()->get_w(),
+                       get_output()->get_h(),
+                       0,
+                       0);
+       }
+
+       get_output()->set_opengl_state(VFrame::SCREEN);
+#endif
+       return 0;
+}
+
+
+