X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;ds=sidebyside;f=cinelerra-5.1%2Fplugins%2Fscale%2Fscale.C;fp=cinelerra-5.1%2Fplugins%2Fscale%2Fscale.C;h=f4285f40d89164e73bdf3777a35a71e77c137be2;hb=30bdb85eb33a8ee7ba675038a86c6be59c43d7bd;hp=0000000000000000000000000000000000000000;hpb=52fcc46226f9df46f9ce9d0566dc568455a7db0b;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/plugins/scale/scale.C b/cinelerra-5.1/plugins/scale/scale.C new file mode 100644 index 00000000..f4285f40 --- /dev/null +++ b/cinelerra-5.1/plugins/scale/scale.C @@ -0,0 +1,306 @@ + +/* + * 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 + * + */ + +#include "clip.h" +#include "filexml.h" +#include "language.h" +#include "mwindow.h" +#include "pluginserver.h" +#include "scale.h" +#include "scalewin.h" + +#include + + +REGISTER_PLUGIN(ScaleMain) + + + +ScaleConfig::ScaleConfig() +{ + type = FIXED_SCALE; + x_factor = y_factor = 1; + width = height = 0; + constrain = 0; +} + +void ScaleConfig::copy_from(ScaleConfig &src) +{ + type = src.type; + x_factor = src.x_factor; + y_factor = src.y_factor; + constrain = src.constrain; + width = src.width; + height = src.height; +} +int ScaleConfig::equivalent(ScaleConfig &src) +{ + return type != src.type ? 0 : type == FIXED_SCALE ? + EQUIV(x_factor, src.x_factor) && EQUIV(y_factor, src.y_factor) && + constrain == src.constrain : + width == src.width && height == src.height; +} + +void ScaleConfig::interpolate(ScaleConfig &prev, ScaleConfig &next, + int64_t prev_frame, int64_t next_frame, int64_t current_frame) +{ + double u = (double)(next_frame - current_frame) / (next_frame - prev_frame); + double v = 1. - u; + + this->type = prev.type; + this->x_factor = u*prev.x_factor + v*next.x_factor; + this->y_factor = u*prev.y_factor + v*next.y_factor; + this->constrain = prev.constrain; + this->width = u*prev.width + v*next.width; + this->height = u*prev.height + v*next.height; +} + + + +ScaleMain::ScaleMain(PluginServer *server) + : PluginVClient(server) +{ + this->server = server; + overlayer = 0; +} + +ScaleMain::~ScaleMain() +{ + if(overlayer) delete overlayer; +} + +const char* ScaleMain::plugin_title() { return _("Scale"); } +int ScaleMain::is_realtime() { return 1; } + + + +LOAD_CONFIGURATION_MACRO(ScaleMain, ScaleConfig) + + +void ScaleMain::set_type(int type) +{ + if( type != config.type ) { + config.type = type; + ScaleWin *swin = (ScaleWin *)thread->window; + int fixed_scale = type == FIXED_SCALE ? 1 : 0; + swin->use_scale->update(fixed_scale); + swin->x_factor->enabled = fixed_scale; + swin->y_factor->enabled = fixed_scale; + int fixed_size = 1 - fixed_scale; + swin->use_size->update(fixed_size); + swin->width->enabled = fixed_size; + swin->height->enabled = fixed_size; + send_configure_change(); + } +} + +void ScaleMain::save_data(KeyFrame *keyframe) +{ + FileXML output; + +// cause data to be stored directly in text + output.set_shared_output(keyframe->get_data(), MESSAGESIZE); + +// Store data + output.tag.set_title("SCALE"); + output.tag.set_property("TYPE", config.type); + output.tag.set_property("X_FACTOR", config.x_factor); + output.tag.set_property("Y_FACTOR", config.y_factor); + output.tag.set_property("WIDTH", config.width); + output.tag.set_property("HEIGHT", config.height); + output.tag.set_property("CONSTRAIN", config.constrain); + output.append_tag(); + output.tag.set_title("/SCALE"); + output.append_tag(); + output.append_newline(); + output.terminate_string(); +// data is now in *text +} + +void ScaleMain::read_data(KeyFrame *keyframe) +{ + FileXML input; + + input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data())); + + int result = 0; + config.constrain = 0; + + while(!result) + { + result = input.read_tag(); + + if(!result) + { + if(input.tag.title_is("SCALE")) + { + config.type = input.tag.get_property("TYPE", config.type); + config.x_factor = input.tag.get_property("X_FACTOR", config.x_factor); + config.y_factor = input.tag.get_property("Y_FACTOR", config.y_factor); + config.constrain = input.tag.get_property("CONSTRAIN", config.constrain); + config.width = input.tag.get_property("WIDTH", config.x_factor); + config.height = input.tag.get_property("HEIGHT", config.y_factor); + } + } + } +} + + + + + + + + +int ScaleMain::process_buffer(VFrame *frame, + int64_t start_position, + double frame_rate) +{ + VFrame *input, *output; + input = output = frame; + + load_configuration(); + read_frame(frame, 0, start_position, frame_rate, get_use_opengl()); + +// No scaling + if( config.type == FIXED_SCALE ? + config.x_factor == 1 && config.y_factor == 1 : + config.width == frame->get_w() && config.height == frame->get_h() ) + return 0; + + if(get_use_opengl()) return run_opengl(); + + VFrame *temp_frame = new_temp(frame->get_w(), frame->get_h(), + frame->get_color_model()); + temp_frame->copy_from(frame); + input = temp_frame; + + if(!overlayer) + { + overlayer = new OverlayFrame(PluginClient::get_project_smp() + 1); + } + + +// Perform scaling + float in_x1, in_x2, in_y1, in_y2, out_x1, out_x2, out_y1, out_y2; + calculate_transfer(output, + in_x1, in_x2, in_y1, in_y2, + out_x1, out_x2, out_y1, out_y2); + output->clear_frame(); + +// printf("ScaleMain::process_realtime 3 output=%p input=%p config.x_factor=%f config.y_factor=%f" +// " config.width=%d config.height=%d config.type=%d %f %f %f %f -> %f %f %f %f\n", +// output, input, config.x_factor, config.y_factor, config.width, config.height, config.type, +// in_x1, in_y1, in_x2, in_y2, out_x1, out_y1, out_x2, out_y2); + overlayer->overlay(output, input, + in_x1, in_y1, in_x2, in_y2, + out_x1, out_y1, out_x2, out_y2, + 1, TRANSFER_REPLACE, get_interpolation_type()); + + return 0; +} + +void ScaleMain::calculate_transfer(VFrame *frame, + float &in_x1, float &in_x2, float &in_y1, float &in_y2, + float &out_x1, float &out_x2, float &out_y1, float &out_y2) +{ + float fw = (float)frame->get_w(); + float fh = (float)frame->get_h(); + in_x1 = in_y1 = 0; + in_x2 = fw; + in_y2 = fh; + float x_factor = config.type == FIXED_SCALE ? config.x_factor : + in_x2 > 0. ? (float)config.width / in_x2 : 0; + float y_factor = config.type == FIXED_SCALE ? config.y_factor : + in_y2 > 0. ? (float)config.height / in_y2 : 0; + + float fw2 = fw/2, fw2s = fw2*x_factor; + float fh2 = fh/2, fh2s = fh2*y_factor; + out_x1 = fw2 - fw2s; + out_x2 = fw2 + fw2s; + out_y1 = fh2 - fh2s; + out_y2 = fh2 + fh2s; + + if(out_x1 < 0) { + in_x1 = x_factor>0 ? in_x1 - out_x1/x_factor : 0; + out_x1 = 0; + } + + if(out_x2 > frame->get_w()) { + in_x2 = x_factor>0 ? in_x2 - (out_x2-frame->get_w())/x_factor : 0; + out_x2 = frame->get_w(); + } + + if(out_y1 < 0) { + in_y1 = y_factor>0 ? in_y1 - out_y1/y_factor : 0; + out_y1 = 0; + } + + if(out_y2 > frame->get_h()) { + in_y2 = y_factor>0 ? in_y2 - (out_y2-frame->get_h())/y_factor : 0; + out_y2 = frame->get_h(); + } +} + +int ScaleMain::handle_opengl() +{ +#ifdef HAVE_GL + float in_x1, in_x2, in_y1, in_y2, out_x1, out_x2, out_y1, out_y2; + calculate_transfer(get_output(), + in_x1, in_x2, in_y1, in_y2, + out_x1, out_x2, out_y1, out_y2); + + get_output()->to_texture(); + get_output()->enable_opengl(); + get_output()->init_screen(); + get_output()->clear_pbuffer(); + get_output()->bind_texture(0); + get_output()->draw_texture( + in_x1, in_y1, in_x2, in_y2, + out_x1, out_y1, out_x2, out_y2); + get_output()->set_opengl_state(VFrame::SCREEN); +#endif + return 0; +} + + + +NEW_WINDOW_MACRO(ScaleMain, ScaleWin) + +void ScaleMain::update_gui() +{ + if(thread) + { + load_configuration(); + thread->window->lock_window(); + set_type(config.type); + ScaleWin *swin = (ScaleWin *)thread->window; + swin->x_factor->update(config.x_factor); + swin->y_factor->update(config.y_factor); + swin->width->update((int64_t)config.width); + swin->height->update((int64_t)config.height); + swin->constrain->update(config.constrain); + thread->window->unlock_window(); + } +} + + +