--- /dev/null
+
+/*
+ * 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 "bcdisplayinfo.h"
+#include "clip.h"
+#include "bchash.h"
+#include "filexml.h"
+#include "language.h"
+#include "swapchannels.h"
+#include "vframe.h"
+
+
+
+#include <stdint.h>
+#include <string.h>
+
+
+
+
+
+
+REGISTER_PLUGIN(SwapMain)
+
+
+
+
+
+
+
+
+SwapConfig::SwapConfig()
+{
+ red = RED_SRC;
+ green = GREEN_SRC;
+ blue = BLUE_SRC;
+ alpha = ALPHA_SRC;
+}
+
+
+int SwapConfig::equivalent(SwapConfig &that)
+{
+ return (red == that.red &&
+ green == that.green &&
+ blue == that.blue &&
+ alpha == that.alpha);
+}
+
+void SwapConfig::copy_from(SwapConfig &that)
+{
+ red = that.red;
+ green = that.green;
+ blue = that.blue;
+ alpha = that.alpha;
+}
+
+
+
+
+
+
+
+
+SwapWindow::SwapWindow(SwapMain *plugin)
+ : PluginClientWindow(plugin,
+ 250,
+ 170,
+ 250,
+ 170,
+ 0)
+{
+ this->plugin = plugin;
+}
+
+SwapWindow::~SwapWindow()
+{
+}
+
+
+void SwapWindow::create_objects()
+{
+ int x = 10, y = 10;
+ int margin = 30;
+
+ add_subwindow(new BC_Title(x, y, _("Swap channels")));
+ y += margin;
+ add_subwindow(new BC_Title(x + 160, y + 5, _("-> Red")));
+ add_subwindow(red = new SwapMenu(plugin, &(plugin->config.red), x, y));
+ red->create_objects();
+ y += margin;
+ add_subwindow(new BC_Title(x + 160, y + 5, _("-> Green")));
+ add_subwindow(green = new SwapMenu(plugin, &(plugin->config.green), x, y));
+ green->create_objects();
+ y += margin;
+ add_subwindow(new BC_Title(x + 160, y + 5, _("-> Blue")));
+ add_subwindow(blue = new SwapMenu(plugin, &(plugin->config.blue), x, y));
+ blue->create_objects();
+ y += margin;
+ add_subwindow(new BC_Title(x + 160, y + 5, _("-> Alpha")));
+ add_subwindow(alpha = new SwapMenu(plugin, &(plugin->config.alpha), x, y));
+ alpha->create_objects();
+
+ show_window();
+ flush();
+}
+
+
+
+
+
+
+
+
+
+SwapMenu::SwapMenu(SwapMain *client, int *output, int x, int y)
+ : BC_PopupMenu(x, y, 150, client->output_to_text(*output))
+{
+ this->client = client;
+ this->output = output;
+}
+
+int SwapMenu::handle_event()
+{
+ client->send_configure_change();
+ return 1;
+}
+
+void SwapMenu::create_objects()
+{
+ add_item(new SwapItem(this, client->output_to_text(RED_SRC)));
+ add_item(new SwapItem(this, client->output_to_text(GREEN_SRC)));
+ add_item(new SwapItem(this, client->output_to_text(BLUE_SRC)));
+ add_item(new SwapItem(this, client->output_to_text(ALPHA_SRC)));
+ add_item(new SwapItem(this, client->output_to_text(NO_SRC)));
+ add_item(new SwapItem(this, client->output_to_text(MAX_SRC)));
+}
+
+
+
+
+SwapItem::SwapItem(SwapMenu *menu, const char *title)
+ : BC_MenuItem(title)
+{
+ this->menu = menu;
+}
+
+int SwapItem::handle_event()
+{
+ menu->set_text(get_text());
+ *(menu->output) = menu->client->text_to_output(get_text());
+ menu->handle_event();
+ return 1;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+SwapMain::SwapMain(PluginServer *server)
+ : PluginVClient(server)
+{
+ reset();
+
+}
+
+SwapMain::~SwapMain()
+{
+
+
+// if(temp) delete temp;
+}
+
+void SwapMain::reset()
+{
+ temp = 0;
+}
+
+
+const char* SwapMain::plugin_title() { return _("Swap channels"); }
+int SwapMain::is_synthesis() { return 1; }
+int SwapMain::is_realtime() { return 1; }
+
+NEW_WINDOW_MACRO(SwapMain, SwapWindow)
+
+
+void SwapMain::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("SWAPCHANNELS");
+ output.tag.set_property("RED", config.red);
+ output.tag.set_property("GREEN", config.green);
+ output.tag.set_property("BLUE", config.blue);
+ output.tag.set_property("ALPHA", config.alpha);
+ output.append_tag();
+ output.tag.set_title("/SWAPCHANNELS");
+ output.append_tag();
+ output.append_newline();
+ output.terminate_string();
+// data is now in *text
+}
+
+void SwapMain::read_data(KeyFrame *keyframe)
+{
+ FileXML input;
+
+ input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
+
+ int result = 0;
+
+ while(!result)
+ {
+ result = input.read_tag();
+
+ if(!result)
+ {
+ if(input.tag.title_is("SWAPCHANNELS"))
+ {
+ config.red = input.tag.get_property("RED", config.red);
+ config.green = input.tag.get_property("GREEN", config.green);
+ config.blue = input.tag.get_property("BLUE", config.blue);
+ config.alpha = input.tag.get_property("ALPHA", config.alpha);
+ }
+ }
+ }
+}
+
+void SwapMain::update_gui()
+{
+ if(thread)
+ {
+ load_configuration();
+ thread->window->lock_window();
+ ((SwapWindow*)thread->window)->red->set_text(output_to_text(config.red));
+ ((SwapWindow*)thread->window)->green->set_text(output_to_text(config.green));
+ ((SwapWindow*)thread->window)->blue->set_text(output_to_text(config.blue));
+ ((SwapWindow*)thread->window)->alpha->set_text(output_to_text(config.alpha));
+ thread->window->unlock_window();
+ }
+}
+
+
+int SwapMain::load_configuration()
+{
+ KeyFrame *prev_keyframe;
+ prev_keyframe = get_prev_keyframe(get_source_position());
+
+ read_data(prev_keyframe);
+ return 1;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#define MAXMINSRC(src, min, max) \
+ (src == MAX_SRC ? max : min)
+
+#define SWAP_CHANNELS(type, min, max, components) \
+{ \
+ int h = frame->get_h(); \
+ int w = frame->get_w(); \
+ int red = config.red; \
+ int green = config.green; \
+ int blue = config.blue; \
+ int alpha = config.alpha; \
+ \
+ if(components == 3) \
+ { \
+ if(red == ALPHA_SRC) red = MAX_SRC; \
+ if(green == ALPHA_SRC) green = MAX_SRC; \
+ if(blue == ALPHA_SRC) blue = MAX_SRC; \
+ } \
+ \
+ \
+ for(int i = 0; i < h; i++) \
+ { \
+ type *inrow = (type*)frame->get_rows()[i]; \
+ type *outrow = (type*)temp->get_rows()[i]; \
+ \
+ for(int j = 0; j < w; j++) \
+ { \
+ if(red < 4) \
+ *outrow++ = *(inrow + red); \
+ else \
+ *outrow++ = MAXMINSRC(red, 0, max); \
+ \
+ if(green < 4) \
+ *outrow++ = *(inrow + green); \
+ else \
+ *outrow++ = MAXMINSRC(green, min, max); \
+ \
+ if(blue < 4) \
+ *outrow++ = *(inrow + blue); \
+ else \
+ *outrow++ = MAXMINSRC(blue, min, max); \
+ \
+ if(components == 4) \
+ { \
+ if(alpha < 4) \
+ *outrow++ = *(inrow + alpha); \
+ else \
+ *outrow++ = MAXMINSRC(alpha, 0, max); \
+ } \
+ \
+ inrow += components; \
+ } \
+ } \
+ \
+ frame->copy_from(temp); \
+}
+
+
+
+int SwapMain::process_buffer(VFrame *frame,
+ int64_t start_position,
+ double frame_rate)
+{
+ load_configuration();
+
+ read_frame(frame,
+ 0,
+ start_position,
+ frame_rate,
+ get_use_opengl());
+
+
+// Use hardware
+ if(get_use_opengl())
+ {
+ run_opengl();
+ return 0;
+ }
+
+
+ temp = new_temp(frame->get_w(),
+ frame->get_h(),
+ frame->get_color_model());
+
+ switch(frame->get_color_model())
+ {
+ case BC_RGB_FLOAT:
+ SWAP_CHANNELS(float, 0, 1, 3);
+ break;
+ case BC_RGBA_FLOAT:
+ SWAP_CHANNELS(float, 0, 1, 4);
+ break;
+ case BC_RGB888:
+ SWAP_CHANNELS(unsigned char, 0, 0xff, 3);
+ break;
+ case BC_YUV888:
+ SWAP_CHANNELS(unsigned char, 0x80, 0xff, 3);
+ break;
+ case BC_RGBA8888:
+ SWAP_CHANNELS(unsigned char, 0, 0xff, 4);
+ break;
+ case BC_YUVA8888:
+ SWAP_CHANNELS(unsigned char, 0x80, 0xff, 4);
+ break;
+ }
+
+
+ return 0;
+}
+
+
+const char* SwapMain::output_to_text(int value)
+{
+ switch(value)
+ {
+ case RED_SRC:
+ return _("Red");
+ break;
+ case GREEN_SRC:
+ return _("Green");
+ break;
+ case BLUE_SRC:
+ return _("Blue");
+ break;
+ case ALPHA_SRC:
+ return _("Alpha");
+ break;
+ case NO_SRC:
+ return "0%";
+ break;
+ case MAX_SRC:
+ return "100%";
+ break;
+ default:
+ return "";
+ break;
+ }
+}
+
+int SwapMain::text_to_output(const char *text)
+{
+ if(!strcmp(text, _("Red"))) return RED_SRC;
+ if(!strcmp(text, _("Green"))) return GREEN_SRC;
+ if(!strcmp(text, _("Blue"))) return BLUE_SRC;
+ if(!strcmp(text, _("Alpha"))) return ALPHA_SRC;
+ if(!strcmp(text, "0%")) return NO_SRC;
+ if(!strcmp(text, "100%")) return MAX_SRC;
+ return 0;
+}
+
+int SwapMain::handle_opengl()
+{
+#ifdef HAVE_GL
+
+ char output_frag[BCTEXTLEN];
+ sprintf(output_frag,
+ "uniform sampler2D tex;\n"
+ "uniform float chroma_offset;\n"
+ "void main()\n"
+ "{\n"
+ " vec4 in_color = texture2D(tex, gl_TexCoord[0].st);\n"
+ " vec4 out_color;\n");
+
+#define COLOR_SWITCH(config, variable) \
+ strcat(output_frag, " out_color." variable " = "); \
+ switch(config) \
+ { \
+ case RED_SRC: strcat(output_frag, "in_color.r;\n"); break; \
+ case GREEN_SRC: strcat(output_frag, "in_color.g;\n"); break; \
+ case BLUE_SRC: strcat(output_frag, "in_color.b;\n"); break; \
+ case ALPHA_SRC: strcat(output_frag, "in_color.a;\n"); break; \
+ case NO_SRC: strcat(output_frag, "chroma_offset;\n"); break; \
+ case MAX_SRC: strcat(output_frag, "1.0;\n"); break; \
+ }
+
+
+ COLOR_SWITCH(config.red, "r");
+ COLOR_SWITCH(config.green, "g");
+ COLOR_SWITCH(config.blue, "b");
+ COLOR_SWITCH(config.alpha, "a");
+
+ strcat(output_frag,
+ " gl_FragColor = out_color;\n"
+ "}\n");
+
+ get_output()->to_texture();
+ get_output()->enable_opengl();
+ get_output()->init_screen();
+ get_output()->clear_pbuffer();
+ get_output()->bind_texture(0);
+
+ unsigned int shader_id = VFrame::make_shader(0,
+ output_frag,
+ 0);
+ glUseProgram(shader_id);
+ glUniform1i(glGetUniformLocation(shader_id, "tex"), 0);
+ glUniform1f(glGetUniformLocation(shader_id, "chroma_offset"),
+ BC_CModels::is_yuv(get_output()->get_color_model()) ? 0.5 : 0.0);
+
+ get_output()->draw_texture();
+ glUseProgram(0);
+ get_output()->set_opengl_state(VFrame::SCREEN);
+#endif
+ return 0;
+}
+
+
+