X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fplugins%2Fmirror%2Fmirror.C;fp=cinelerra-5.1%2Fplugins%2Fmirror%2Fmirror.C;h=847e587a67a4d8adbef934718d5a3a2aee8ff206;hb=07a0e1f6f49dc7c4229a3a296b722a0571c17e81;hp=0000000000000000000000000000000000000000;hpb=7befc439d48ecf3591a0e8f420a447e8c1ec7250;p=goodguy%2Fcinelerra.git diff --git a/cinelerra-5.1/plugins/mirror/mirror.C b/cinelerra-5.1/plugins/mirror/mirror.C new file mode 100644 index 00000000..847e587a --- /dev/null +++ b/cinelerra-5.1/plugins/mirror/mirror.C @@ -0,0 +1,644 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 + * + */ + +/* + * 2023. Derivative by Flip plugin. +*/ + +#include "clip.h" +#include "bccmodels.h" +#include "bchash.h" +#include "filexml.h" +#include "mirror.h" +#include "mirrorwindow.h" +#include "language.h" +#include "mwindow.h" + +#include +#include +#include + +REGISTER_PLUGIN(MirrorMain) + + + + + + +MirrorConfig::MirrorConfig() +{ + reset(RESET_DEFAULT_SETTINGS); +} + +void MirrorConfig::reset(int clear) +{ + switch(clear) { + case RESET_REFLECTION_CENTER_X : + reflection_center_x = 50.00; + mirror_horizontal = 1; + mirror_swaphorizontal = 0; + break; + case RESET_REFLECTION_CENTER_Y : + reflection_center_y = 50.00; + mirror_vertical = 1; + mirror_swapvertical = 0; + break; + case RESET_ALL : + case RESET_DEFAULT_SETTINGS : + default: + mirror_horizontal = 1; + mirror_swaphorizontal = 0; + mirror_vertical = 0; + mirror_swapvertical = 0; + reflection_center_enable = 0; + reflection_center_x = 50.00; + reflection_center_y = 50.00; + break; + } +} + +void MirrorConfig::copy_from(MirrorConfig &that) +{ + mirror_horizontal = that.mirror_horizontal; + mirror_swaphorizontal = that.mirror_swaphorizontal; + mirror_vertical = that.mirror_vertical; + mirror_swapvertical = that.mirror_swapvertical; + reflection_center_enable = that.reflection_center_enable; + reflection_center_x = that.reflection_center_x; + reflection_center_y = that.reflection_center_y; +} + +int MirrorConfig::equivalent(MirrorConfig &that) +{ + return EQUIV(mirror_horizontal, that.mirror_horizontal) && + EQUIV(mirror_swaphorizontal, that.mirror_swaphorizontal) && + EQUIV(mirror_vertical, that.mirror_vertical) && + EQUIV(mirror_swapvertical, that.mirror_swapvertical) && + EQUIV(reflection_center_enable, that.reflection_center_enable) && + EQUIV(reflection_center_x, that.reflection_center_x) && + EQUIV(reflection_center_y, that.reflection_center_y); +} + +void MirrorConfig::interpolate(MirrorConfig &prev, + MirrorConfig &next, + int64_t prev_frame, + int64_t next_frame, + int64_t current_frame) +{ + double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame); + double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame); + + this->mirror_horizontal = prev.mirror_horizontal; + this->mirror_swaphorizontal = prev.mirror_swaphorizontal; + this->mirror_vertical = prev.mirror_vertical; + this->mirror_swapvertical = prev.mirror_swapvertical; + this->reflection_center_enable = prev.reflection_center_enable; + this->reflection_center_x = prev.reflection_center_x * prev_scale + next.reflection_center_x * next_scale; + this->reflection_center_y = prev.reflection_center_y * prev_scale + next.reflection_center_y * next_scale; +} + + + + + + + + + + +MirrorMain::MirrorMain(PluginServer *server) + : PluginVClient(server) +{ + +} + +MirrorMain::~MirrorMain() +{ + +} + +const char* MirrorMain::plugin_title() { return N_("Mirror"); } +int MirrorMain::is_realtime() { return 1; } + + +#define SWAPCOPY_PIXELS(components, in, out) \ +{ \ + in[0] = out[0]; \ + in[1] = out[1]; \ + in[2] = out[2]; \ + if(components == 4) \ + { \ + in[3] = out[3]; \ + } \ +} + + +#define MIRROR_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.reflection_center_enable) \ + { \ + /* HORIZONTAL ONLY */ \ + if(config.mirror_horizontal && !config.mirror_vertical && !config.mirror_swaphorizontal) \ + { \ + 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++) \ + { \ + SWAPCOPY_PIXELS(components, output_row, input_row); \ + input_row += components; \ + output_row -= components; \ + } \ + } \ + } \ + /* HORIZONTAL SWAP ONLY */ \ + else if(config.mirror_horizontal && !config.mirror_vertical && config.mirror_swaphorizontal) \ + { \ + 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++) \ + { \ + SWAPCOPY_PIXELS(components, input_row, output_row); \ + input_row += components; \ + output_row -= components; \ + } \ + } \ + } \ + /* VERTICAL ONLY */ \ + else if(config.mirror_vertical && !config.mirror_horizontal && !config.mirror_swapvertical) \ + { \ + 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++) \ + { \ + SWAPCOPY_PIXELS(components, output_row, input_row); \ + output_row += components; \ + input_row += components; \ + } \ + } \ + } \ + /* VERTICAL SWAP ONLY */ \ + else if(config.mirror_vertical && !config.mirror_horizontal && config.mirror_swapvertical) \ + { \ + 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++) \ + { \ + SWAPCOPY_PIXELS(components, input_row, output_row); \ + output_row += components; \ + input_row += components; \ + } \ + } \ + } \ + /* HORIZONTAL and VERTICAL */ \ + else if(config.mirror_horizontal && config.mirror_vertical && !config.mirror_swaphorizontal && !config.mirror_swapvertical) \ + { \ + /* HORIZONTAL ONLY */ \ + 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++) \ + { \ + SWAPCOPY_PIXELS(components, output_row, input_row); \ + input_row += components; \ + output_row -= components; \ + } \ + } \ + /* VERTICAL ONLY */ \ + 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++) \ + { \ + SWAPCOPY_PIXELS(components, output_row, input_row); \ + output_row += components; \ + input_row += components; \ + } \ + } \ + } \ + /* HORIZONTAL with SWAP and VERTICAL with SWAP */ \ + else if(config.mirror_horizontal && config.mirror_vertical && config.mirror_swaphorizontal && config.mirror_swapvertical) \ + { \ + /* HORIZONTAL SWAP ONLY */ \ + 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++) \ + { \ + SWAPCOPY_PIXELS(components, input_row, output_row); \ + input_row += components; \ + output_row -= components; \ + } \ + } \ + /* VERTICAL SWAP ONLY */ \ + 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++) \ + { \ + SWAPCOPY_PIXELS(components, input_row, output_row); \ + output_row += components; \ + input_row += components; \ + } \ + } \ + } \ + /* HORIZONTAL with SWAP and VERTICAL ONLY */ \ + else if(config.mirror_horizontal && config.mirror_vertical && config.mirror_swaphorizontal && !config.mirror_swapvertical) \ + { \ + /* HORIZONTAL SWAP ONLY */ \ + 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++) \ + { \ + SWAPCOPY_PIXELS(components, input_row, output_row); \ + input_row += components; \ + output_row -= components; \ + } \ + } \ + /* VERTICAL ONLY */ \ + 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++) \ + { \ + SWAPCOPY_PIXELS(components, output_row, input_row); \ + output_row += components; \ + input_row += components; \ + } \ + } \ + } \ + /* HORIZONTAL ONLY and VERTICAL with SWAP */ \ + else if(config.mirror_horizontal && config.mirror_vertical && !config.mirror_swaphorizontal && config.mirror_swapvertical) \ + { \ + /* HORIZONTAL ONLY */ \ + 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++) \ + { \ + SWAPCOPY_PIXELS(components, output_row, input_row); \ + input_row += components; \ + output_row -= components; \ + } \ + } \ + /* VERTICAL SWAP ONLY */ \ + 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++) \ + { \ + SWAPCOPY_PIXELS(components, input_row, output_row); \ + output_row += components; \ + input_row += components; \ + } \ + } \ + } \ + } \ + \ + else if(config.reflection_center_enable) \ + { \ + if(config.mirror_vertical) \ + { \ + int y_pixel = (int)round(config.reflection_center_y / 100.00 * h); \ + if(config.reflection_center_y < 50.00) \ + { \ + int valueY_source = y_pixel + 1; \ + int valueY_destination = y_pixel - 1; \ + for(int i = 0; i < y_pixel; i++) \ + { \ + input_row = input_rows[valueY_source]; \ + output_row = output_rows[valueY_destination]; \ + for(k = 0; k < w; k++) \ + { \ + SWAPCOPY_PIXELS(components, output_row, input_row); \ + output_row += components; \ + input_row += components; \ + } \ + valueY_source += 1; \ + valueY_destination -= 1; \ + } \ + } \ + else if(config.reflection_center_y > 50.00) \ + { \ + int valueY_source = y_pixel - 1; \ + int valueY_destination = y_pixel + 1; \ + for(int i = 0; i < (h - y_pixel - 1); i++) \ + { \ + input_row = input_rows[valueY_source]; \ + output_row = output_rows[valueY_destination]; \ + for(k = 0; k < w; k++) \ + { \ + SWAPCOPY_PIXELS(components, output_row, input_row); \ + output_row += components; \ + input_row += components; \ + } \ + valueY_source -= 1; \ + valueY_destination += 1; \ + } \ + } \ + else /* Y_PERCENT == 50.00 */ \ + { \ + 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++) \ + { \ + SWAPCOPY_PIXELS(components, output_row, input_row); \ + output_row += components; \ + input_row += components; \ + } \ + } \ + } \ + } \ + \ + if(config.mirror_horizontal) \ + { \ + int x_pixel = (int)round(config.reflection_center_x / 100.00 * w); \ + if(config.reflection_center_x < 50.00) \ + { \ + int valueX_source = x_pixel + 1; \ + int valueX_destination = x_pixel - 1; \ + for(i = 0; i < h; i++) \ + { \ + input_row = input_rows[i] + valueX_source * components; \ + output_row = output_rows[i] + valueX_destination * components; \ + for(k = 0; k < x_pixel; k++) \ + { \ + SWAPCOPY_PIXELS(components, output_row, input_row); \ + output_row -= components; \ + input_row += components; \ + } \ + } \ + } \ + else if(config.reflection_center_x > 50.00) \ + { \ + int valueX_source = x_pixel - 1; \ + int valueX_destination = x_pixel + 1; \ + for(i = 0; i < h; i++) \ + { \ + input_row = input_rows[i] + valueX_source * components; \ + output_row = output_rows[i] + valueX_destination * components; \ + for(k = 0; k < (w - x_pixel - 1); k++) \ + { \ + SWAPCOPY_PIXELS(components, output_row, input_row); \ + output_row += components; \ + input_row -= components; \ + } \ + } \ + } \ + else /* X_PERCENT == 50.00 */ \ + { \ + 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++) \ + { \ + SWAPCOPY_PIXELS(components, output_row, input_row); \ + input_row += components; \ + output_row -= components; \ + } \ + } \ + } \ + } \ + } \ +} + +int MirrorMain::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(); + +// THIS CODE WAS FOR the FLIP Plugin!!! +/* + read_frame(frame, + 0, + get_source_position(), + get_framerate(), + get_use_opengl()); + + if(get_use_opengl()) + { + if(config.mirror_vertical || config.mirror_horizontal) + return run_opengl(); + else + return 0; + } +*/ + read_frame(frame, + 0, + start_position, + frame_rate, + get_use_opengl()); + + if(config.mirror_vertical || config.mirror_horizontal) + { + switch(colormodel) + { + case BC_RGB888: + case BC_YUV888: + MIRROR_MACRO(unsigned char, 3); + break; + case BC_RGB_FLOAT: + MIRROR_MACRO(float, 3); + break; + case BC_RGB161616: + case BC_YUV161616: + MIRROR_MACRO(uint16_t, 3); + break; + case BC_RGBA8888: + case BC_YUVA8888: + MIRROR_MACRO(unsigned char, 4); + break; + case BC_RGBA_FLOAT: + MIRROR_MACRO(float, 4); + break; + case BC_RGBA16161616: + case BC_YUVA16161616: + MIRROR_MACRO(uint16_t, 4); + break; + } + } + return 0; +} + + +NEW_WINDOW_MACRO(MirrorMain, MirrorWindow) +LOAD_CONFIGURATION_MACRO(MirrorMain, MirrorConfig) + +void MirrorMain::update_gui() +{ + if(thread) + { + load_configuration(); + thread->window->lock_window(); + ((MirrorWindow*)thread->window)->mirror_horizontal->update((int)config.mirror_horizontal); + ((MirrorWindow*)thread->window)->mirror_swaphorizontal->update((int)config.mirror_swaphorizontal); + ((MirrorWindow*)thread->window)->mirror_vertical->update((int)config.mirror_vertical); + ((MirrorWindow*)thread->window)->mirror_swapvertical->update((int)config.mirror_swapvertical); + ((MirrorWindow*)thread->window)->reflection_center_enable->update(config.reflection_center_enable); + ((MirrorWindow*)thread->window)->reflection_center_x_text->update(config.reflection_center_x); + ((MirrorWindow*)thread->window)->reflection_center_x_slider->update(config.reflection_center_x); + ((MirrorWindow*)thread->window)->reflection_center_y_text->update(config.reflection_center_y); + ((MirrorWindow*)thread->window)->reflection_center_y_slider->update(config.reflection_center_y); + // Needed to update Enable-Disable GUI when "Show controls" is pressed. + ((MirrorWindow*)thread->window)->update_reflection_center_enable(); + thread->window->unlock_window(); + } +} + +void MirrorMain::save_data(KeyFrame *keyframe) +{ + FileXML output; + +// cause data to be stored directly in text + output.set_shared_output(keyframe->xbuf); + +// Store data + output.tag.set_title("MIRROR"); + output.tag.set_property("HORIZONTAL", config.mirror_horizontal); + output.tag.set_property("SWAP_HORIZONTAL", config.mirror_swaphorizontal); + output.tag.set_property("VERTICAL", config.mirror_vertical); + output.tag.set_property("SWAP_VERTICAL", config.mirror_swapvertical); + output.tag.set_property("REFLECTION_CENTER_ENABLE", config.reflection_center_enable); + output.tag.set_property("REFLECTION_CENTER_X", config.reflection_center_x); + output.tag.set_property("REFLECTION_CENTER_Y", config.reflection_center_y); + output.append_tag(); + output.tag.set_title("/MIRROR"); + output.append_tag(); + output.append_newline(); + output.terminate_string(); +// data is now in *text +} + +void MirrorMain::read_data(KeyFrame *keyframe) +{ + FileXML input; + + input.set_shared_input(keyframe->xbuf); + + int result = 0; + config.mirror_vertical = config.mirror_horizontal = 0; + config.mirror_swapvertical = config.mirror_swaphorizontal = 0; + + while(!result) + { + result = input.read_tag(); + + if(!result) + { + if(input.tag.title_is("MIRROR")) + { + config.mirror_horizontal = input.tag.get_property("HORIZONTAL", config.mirror_horizontal); + config.mirror_swaphorizontal = input.tag.get_property("SWAP_HORIZONTAL", config.mirror_swaphorizontal); + config.mirror_vertical = input.tag.get_property("VERTICAL", config.mirror_vertical); + config.mirror_swapvertical = input.tag.get_property("SWAP_VERTICAL", config.mirror_swapvertical); + config.reflection_center_enable = input.tag.get_property("REFLECTION_CENTER_ENABLE", config.reflection_center_enable); + config.reflection_center_x = input.tag.get_property("REFLECTION_CENTER_X", config.reflection_center_x); + config.reflection_center_y = input.tag.get_property("REFLECTION_CENTER_Y", config.reflection_center_y); + } + } + } +} + + +int MirrorMain::handle_opengl() +{ +#ifdef HAVE_GL +// FIXIT. When?! ... THIS CODE WAS FOR the FLIP Plugin!!! +/* + get_output()->to_texture(); + get_output()->enable_opengl(); + get_output()->init_screen(); + get_output()->bind_texture(0); + + if(config.mirror_vertical && !config.mirror_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.mirror_horizontal && !config.mirror_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.mirror_vertical && config.mirror_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; +} + + +