From 63ced327c156ea7fe4448a18b0b1b0f2571dce7e Mon Sep 17 00:00:00 2001 From: Good Guy Date: Sun, 25 Jun 2017 13:30:21 -0600 Subject: [PATCH] rework edge plugin, add crikey plugin, text tumbler tweak, eyedropper coords --- cinelerra-5.1/cinelerra/cwindowtool.C | 11 +- cinelerra-5.1/cinelerra/cwindowtool.h | 1 + cinelerra-5.1/guicast/bctextbox.C | 34 +- cinelerra-5.1/guicast/bctextbox.h | 2 +- cinelerra-5.1/plugin_defs | 2 +- cinelerra-5.1/plugins/Makefile | 1 + cinelerra-5.1/plugins/crikey/Makefile | 13 + cinelerra-5.1/plugins/crikey/crikey.C | 651 ++++++++++++++++++++ cinelerra-5.1/plugins/crikey/crikey.h | 130 ++++ cinelerra-5.1/plugins/crikey/crikeywindow.C | 360 +++++++++++ cinelerra-5.1/plugins/crikey/crikeywindow.h | 161 +++++ cinelerra-5.1/plugins/crikey/picon.png | Bin 0 -> 3155 bytes cinelerra-5.1/plugins/edge/edge.C | 286 +++------ cinelerra-5.1/plugins/edge/edge.h | 21 +- 14 files changed, 1423 insertions(+), 250 deletions(-) create mode 100644 cinelerra-5.1/plugins/crikey/Makefile create mode 100644 cinelerra-5.1/plugins/crikey/crikey.C create mode 100644 cinelerra-5.1/plugins/crikey/crikey.h create mode 100644 cinelerra-5.1/plugins/crikey/crikeywindow.C create mode 100644 cinelerra-5.1/plugins/crikey/crikeywindow.h create mode 100644 cinelerra-5.1/plugins/crikey/picon.png diff --git a/cinelerra-5.1/cinelerra/cwindowtool.C b/cinelerra-5.1/cinelerra/cwindowtool.C index ee1c1044..caf0bf82 100644 --- a/cinelerra-5.1/cinelerra/cwindowtool.C +++ b/cinelerra-5.1/cinelerra/cwindowtool.C @@ -480,7 +480,9 @@ void CWindowEyedropGUI::create_objects() int y = margin; int x2 = 70; lock_window("CWindowEyedropGUI::create_objects"); - BC_Title *title1, *title2, *title3, *title4, *title5, *title6, *title7; + BC_Title *title0, *title1, *title2, *title3, *title4, *title5, *title6, *title7; + add_subwindow(title0 = new BC_Title(x, y,_("X,Y:"))); + y += title0->get_h() + margin; add_subwindow(title7 = new BC_Title(x, y, _("Radius:"))); y += BC_TextBox::calculate_h(this, MEDIUMFONT, 1, 1) + margin; @@ -497,6 +499,7 @@ void CWindowEyedropGUI::create_objects() y += title5->get_h() + margin; add_subwindow(title6 = new BC_Title(x, y, "V:")); + add_subwindow(current = new BC_Title(x2, title0->get_y(), "")); radius = new CWindowCoord(this, x2, title7->get_y(), mwindow->edl->session->eyedrop_radius); @@ -520,6 +523,12 @@ void CWindowEyedropGUI::create_objects() void CWindowEyedropGUI::update() { + char string[BCTEXTLEN]; + sprintf(string, "%d, %d", + thread->gui->eyedrop_x, + thread->gui->eyedrop_y); + current->update(string); + radius->update((int64_t)mwindow->edl->session->eyedrop_radius); red->update(mwindow->edl->local_session->red); diff --git a/cinelerra-5.1/cinelerra/cwindowtool.h b/cinelerra-5.1/cinelerra/cwindowtool.h index 2fb3ab9f..5761ae8a 100644 --- a/cinelerra-5.1/cinelerra/cwindowtool.h +++ b/cinelerra-5.1/cinelerra/cwindowtool.h @@ -264,6 +264,7 @@ public: void create_objects(); void update(); + BC_Title *current; CWindowCoord *radius; BC_Title *red, *green, *blue, *y, *u, *v; BC_SubWindow *sample; diff --git a/cinelerra-5.1/guicast/bctextbox.C b/cinelerra-5.1/guicast/bctextbox.C index bd43f1cd..ef3ffb1f 100644 --- a/cinelerra-5.1/guicast/bctextbox.C +++ b/cinelerra-5.1/guicast/bctextbox.C @@ -2561,8 +2561,8 @@ BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup, } BC_TumbleTextBoxText::BC_TumbleTextBoxText(BC_TumbleTextBox *popup, - float default_value, int x, int y) - : BC_TextBox(x, y, popup->text_w, 1, default_value) + float default_value, int x, int y, int precision) + : BC_TextBox(x, y, popup->text_w, 1, default_value, 1, MEDIUMFONT, precision) { this->popup = popup; } @@ -2714,31 +2714,17 @@ int BC_TumbleTextBox::create_objects() { int x = this->x, y = this->y; - if(use_float) - { - parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this, - default_value_f, x, y)); - textbox->set_precision(precision); - } - else - parent_window->add_subwindow(textbox = new BC_TumbleTextBoxText(this, - default_value, x, y)); + textbox = use_float ? + new BC_TumbleTextBoxText(this, default_value_f, x, y, precision) : + new BC_TumbleTextBoxText(this, default_value, x, y); + parent_window->add_subwindow(textbox); x += textbox->get_w(); - if(use_float) - parent_window->add_subwindow(tumbler = new BC_FTumbler(textbox, - min_f, - max_f, - x, - y)); - else - parent_window->add_subwindow(tumbler = new BC_ITumbler(textbox, - min, - max, - x, - y)); - + tumbler = use_float ? + (BC_Tumbler *)new BC_FTumbler(textbox, min_f, max_f, x, y) : + (BC_Tumbler *)new BC_ITumbler(textbox, min, max, x, y); + parent_window->add_subwindow(tumbler); tumbler->set_increment(increment); return 0; } diff --git a/cinelerra-5.1/guicast/bctextbox.h b/cinelerra-5.1/guicast/bctextbox.h index e681f76f..a3db2b69 100644 --- a/cinelerra-5.1/guicast/bctextbox.h +++ b/cinelerra-5.1/guicast/bctextbox.h @@ -453,7 +453,7 @@ class BC_TumbleTextBoxText : public BC_TextBox { public: BC_TumbleTextBoxText(BC_TumbleTextBox *popup, int64_t default_value, int x, int y); - BC_TumbleTextBoxText(BC_TumbleTextBox *popup, float default_value, int x, int y); + BC_TumbleTextBoxText(BC_TumbleTextBox *popup, float default_value, int x, int y, int precision); virtual ~BC_TumbleTextBoxText(); int handle_event(); int button_press_event(); diff --git a/cinelerra-5.1/plugin_defs b/cinelerra-5.1/plugin_defs index 4eba17c5..de386bc7 100644 --- a/cinelerra-5.1/plugin_defs +++ b/cinelerra-5.1/plugin_defs @@ -43,7 +43,7 @@ video_tools := blur decimate delayvideo denoisemjpeg denoisevideo downsample \ unsharp videoscope wave zoomblur plugin_dirs += blending -blending := chromakeyhsv chromakey diffkey +blending := crikey chromakeyhsv chromakey diffkey plugin_dirs += tv_effects tv_effects := deinterlace-cv deinterlace ivtc liveaudio livevideo rgb601 \ diff --git a/cinelerra-5.1/plugins/Makefile b/cinelerra-5.1/plugins/Makefile index c2000234..6b9e9395 100644 --- a/cinelerra-5.1/plugins/Makefile +++ b/cinelerra-5.1/plugins/Makefile @@ -30,6 +30,7 @@ DIRS = \ color3way \ colorbalance \ compressor \ + crikey \ crossfade \ dcoffset \ decimate \ diff --git a/cinelerra-5.1/plugins/crikey/Makefile b/cinelerra-5.1/plugins/crikey/Makefile new file mode 100644 index 00000000..84def470 --- /dev/null +++ b/cinelerra-5.1/plugins/crikey/Makefile @@ -0,0 +1,13 @@ +include ../../plugin_defs + +OBJS := \ + $(OBJDIR)/crikey.o \ + $(OBJDIR)/crikeywindow.o + +PLUGIN = crikey + +include ../../plugin_config + +$(OBJDIR)/crikey.o: crikey.C +$(OBJDIR)/crikeywindow.o: crikeywindow.C + diff --git a/cinelerra-5.1/plugins/crikey/crikey.C b/cinelerra-5.1/plugins/crikey/crikey.C new file mode 100644 index 00000000..ccbb216a --- /dev/null +++ b/cinelerra-5.1/plugins/crikey/crikey.C @@ -0,0 +1,651 @@ +/* + * CINELERRA + * Copyright (C) 1997-2015 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 +#include +#include +#include + +#include "arraylist.h" +#include "bccmodels.h" +#include "cicolors.h" +#include "clip.h" +#include "filexml.h" +#include "crikey.h" +#include "crikeywindow.h" +#include "language.h" +#include "vframe.h" + +// chroma interpolated key, crikey + +REGISTER_PLUGIN(CriKey) + +#if 0 +void crikey_pgm(const char *fn,VFrame *vfrm) +{ + FILE *fp = fopen(fn,"w"); + int w = vfrm->get_w(), h = vfrm->get_h(); + fprintf(fp,"P5\n%d %d\n255\n",w,h); + fwrite(vfrm->get_data(),w,h,fp); + fclose(fp); +} +#endif + +CriKeyConfig::CriKeyConfig() +{ + color = 0x000000; + threshold = 0.5f; + draw_mode = DRAW_ALPHA; + key_mode = KEY_SEARCH; + point_x = point_y = 0; + drag = 0; +} + +int CriKeyConfig::equivalent(CriKeyConfig &that) +{ + return this->color != that.color || + !EQUIV(this->threshold, that.threshold) || + this->draw_mode != that.draw_mode || + this->key_mode != that.key_mode || + !EQUIV(this->point_x, that.point_x) || + !EQUIV(this->point_y, that.point_y) || + this->drag != that.drag ? 0 : 1; +} + +void CriKeyConfig::copy_from(CriKeyConfig &that) +{ + this->color = that.color; + this->threshold = that.threshold; + this->draw_mode = that.draw_mode; + this->key_mode = that.key_mode; + this->point_x = that.point_x; + this->point_y = that.point_y; + this->drag = that.drag; +} + +void CriKeyConfig::interpolate(CriKeyConfig &prev, CriKeyConfig &next, + long prev_frame, long next_frame, long current_frame) +{ + copy_from(prev); + 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->threshold = prev.threshold * prev_scale + next.threshold * next_scale; + switch( prev.key_mode ) { + case KEY_POINT: { + this->point_x = prev.point_x * prev_scale + next.point_x * next_scale; + this->point_y = prev.point_y * prev_scale + next.point_y * next_scale; + break; } + case KEY_SEARCH: + case KEY_SEARCH_ALL: { + float prev_target[3]; set_target(0, prev.color, prev_target); + float next_target[3]; set_target(0, next.color, next_target); + float target[3]; // interpolates rgb components + for( int i=0; i<3; ++i ) + target[i] = prev_target[i] * prev_scale + next_target[i] * next_scale; + set_color(0, target, this->color); + break; } + } +} + +void CriKeyConfig::limits() +{ + bclamp(threshold, 0.0f, 1.0f); + bclamp(draw_mode, 0, DRAW_MODES-1); + bclamp(key_mode, 0, KEY_MODES-1); +} + + +class FillRegion +{ + class segment { public: int y, lt, rt; }; + ArrayList stack; + + void push(int y, int lt, int rt) { + segment &seg = stack.append(); + seg.y = y; seg.lt = lt; seg.rt = rt; + } + void pop(int &y, int <, int &rt) { + segment &seg = stack.last(); + y = seg.y; lt = seg.lt; rt = seg.rt; + stack.remove(); + } + + int w, h, threshold; + uint8_t *data, *mask; + bool edge_pixel(uint8_t *dp) { return *dp; } + +public: + void fill(int x, int y); + void set_threshold(float v) { threshold = v; } + + FillRegion(VFrame *d, VFrame *m); +}; + +FillRegion::FillRegion(VFrame *d, VFrame *m) +{ + threshold = 128; + w = d->get_w(); + h = d->get_h(); + data = d->get_data(); + mask = m->get_data(); +} + +void FillRegion::fill(int x, int y) +{ + push(y, x, x); + + do { + int ilt, irt, lt, rt; + pop(y, ilt, irt); + int ofs = y*w + ilt; + uint8_t *idp = data + ofs, *dp; + uint8_t *imp = mask + ofs, *mp; + for( int x=ilt; x<=irt; ++x,++imp,++idp ) { + if( !*imp || edge_pixel(idp) ) continue; + *imp = 0; + lt = rt = x; + dp = idp; mp = imp; + for( int i=lt; --i>=0; lt=i,*mp=0 ) + if( !*--mp || edge_pixel(--dp) ) break; + dp = idp; mp = imp; + for( int i=rt; ++i< w; rt=i,*mp=0 ) + if( !*++mp || edge_pixel(++dp) ) break; + if( y+1 < h ) push(y+1, lt, rt); + if( y-1 >= 0 ) push(y-1, lt, rt); + } + } while( stack.size() > 0 ); +} + + +CriKey::CriKey(PluginServer *server) + : PluginVClient(server) +{ + engine = 0; + msk = 0; + dst = 0; + diff_pixel = 0; +} + +CriKey::~CriKey() +{ + delete engine; + delete msk; + delete dst; +} + +void CriKeyConfig::set_target(int is_yuv, int color, float *target) +{ + float r = ((color>>16) & 0xff) / 255.0f; + float g = ((color>> 8) & 0xff) / 255.0f; + float b = ((color>> 0) & 0xff) / 255.0f; + if( is_yuv ) { + float y, u, v; + YUV::rgb_to_yuv_f(r,g,b, y,u,v); + target[0] = y; + target[1] = u + 0.5f; + target[2] = v + 0.5f; + } + else { + target[0] = r; + target[1] = g; + target[2] = b; + } +} +void CriKeyConfig::set_color(int is_yuv, float *target, int &color) +{ + float r = target[0]; + float g = target[1]; + float b = target[2]; + if( is_yuv ) { + float y = r, u = g-0.5f, v = b-0.5f; + YUV::yuv_to_rgb_f(y,u,v, r,g,b); + } + int ir = r >= 1 ? 0xff : r < 0 ? 0 : (int)(r * 256); + int ig = g >= 1 ? 0xff : g < 0 ? 0 : (int)(g * 256); + int ib = b >= 1 ? 0xff : b < 0 ? 0 : (int)(b * 256); + color = (ir << 16) | (ig << 8) | (ib << 0); +} + +void CriKey::get_color(int x, int y) +{ + if( x < 0 || x >= w ) return; + if( y < 0 || y >= h ) return; + uint8_t **src_rows = src->get_rows(); + uint8_t *sp = src_rows[y] + x*bpp; + if( is_float ) { + float *fp = (float *)sp; + for( int i=0; iget_rows(); + for( int y=0; y*diff_pixel)(sp); + if( v >= mv ) continue; + mv = v; ix = x; iy = y; + } + } +} +bool CriKey::find_key(int &ix, int &iy, float thr) +{ + uint8_t **src_rows = src->get_rows(); + uint8_t **msk_rows = msk->get_rows(); + int x = ix, y = iy; + for( ; y*diff_pixel)(sp); + if( v < thr ) { + ix = x; iy = y; + return true; + } + } + x = 0; + } + return false; +} + +const char* CriKey::plugin_title() { return _("CriKey"); } +int CriKey::is_realtime() { return 1; } + +NEW_WINDOW_MACRO(CriKey, CriKeyWindow); +LOAD_CONFIGURATION_MACRO(CriKey, CriKeyConfig) + +void CriKey::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("CRIKEY"); + output.tag.set_property("COLOR", config.color); + output.tag.set_property("THRESHOLD", config.threshold); + output.tag.set_property("DRAW_MODE", config.draw_mode); + output.tag.set_property("KEY_MODE", config.key_mode); + output.tag.set_property("POINT_X", config.point_x); + output.tag.set_property("POINT_Y", config.point_y); + output.tag.set_property("DRAG", config.drag); + output.append_tag(); + output.append_newline(); + output.tag.set_title("/CRIKEY"); + output.append_tag(); + output.append_newline(); + output.terminate_string(); +} + +void CriKey::read_data(KeyFrame *keyframe) +{ + FileXML input; + input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data())); + int result = 0; + + while( !(result=input.read_tag()) ) { + if(input.tag.title_is("CRIKEY")) { + config.color = input.tag.get_property("COLOR", config.color); + config.threshold = input.tag.get_property("THRESHOLD", config.threshold); + config.draw_mode = input.tag.get_property("DRAW_MODE", config.draw_mode); + config.key_mode = input.tag.get_property("KEY_MODE", config.key_mode); + config.point_x = input.tag.get_property("POINT_X", config.point_x); + config.point_y = input.tag.get_property("POINT_Y", config.point_y); + config.drag = input.tag.get_property("DRAG", config.drag); + config.limits(); + } + else if(input.tag.title_is("/CRIKEY")) { + result = 1; + } + } + +} + +void CriKey::update_gui() +{ + if( !thread ) return; + if( !load_configuration() ) return; + thread->window->lock_window("CriKey::update_gui"); + CriKeyWindow *window = (CriKeyWindow*)thread->window; + window->update_gui(); + window->flush(); + thread->window->unlock_window(); +} + +void CriKey::draw_alpha(VFrame *msk) +{ + uint8_t **src_rows = src->get_rows(); + uint8_t **msk_rows = msk->get_rows(); + switch( color_model ) { + case BC_RGB_FLOAT: + for( int y=0; yget_rows(); + uint8_t **msk_rows = msk->get_rows(); + float scale = 1 / 255.0f; + switch( color_model ) { + case BC_RGB_FLOAT: + for( int y=0; yget_w(), h = src->get_h(); + color_model = src->get_color_model(); + bpp = BC_CModels::calculate_pixelsize(color_model); + comp = BC_CModels::components(color_model); + if( comp > 3 ) comp = 3; + is_yuv = BC_CModels::is_yuv(color_model); + is_float = BC_CModels::is_float(color_model); + diff_pixel = is_float ? &CriKey::diff_float : &CriKey::diff_uint8; + + read_frame(src, 0, start_position, frame_rate, 0); + + switch( config.key_mode ) { + case KEY_SEARCH: + case KEY_SEARCH_ALL: + set_target(is_yuv, config.color, target); + break; + case KEY_POINT: + get_color(config.point_x, config.point_y); + break; + } + + if( dst && ( dst->get_w() != w || src->get_h() != h ) ) { + delete dst; dst = 0; + } + if( !dst ) + dst = new VFrame(w, h, BC_A8); + memset(dst->get_data(), 0x00, dst->get_data_size()); + + if( !engine ) + engine = new CriKeyEngine(this, + PluginClient::get_project_smp() + 1, + PluginClient::get_project_smp() + 1); + engine->process_packages(); +// copy fill btm/rt edges + int w1 = w-1, h1 = h-1; + uint8_t *dp = dst->get_data(); + if( w1 > 0 ) for( int y=0; y 0 ) for( int x=0; xget_w() != w || msk->get_h() != h ) ) { + delete msk; msk = 0; + } + if( !msk ) + msk = new VFrame(w, h, BC_A8); + memset(msk->get_data(), 0xff, msk->get_data_size()); + + FillRegion fill_region(dst, msk); + fill_region.set_threshold(config.threshold); + + int x = 0, y = 0; + switch( config.key_mode ) { + case KEY_SEARCH: + min_key(x, y); + fill_region.fill(x, y); + break; + case KEY_SEARCH_ALL: + while( find_key(x, y, config.threshold) ) { + fill_region.fill(x, y); + ++x; + } + break; + case KEY_POINT: + x = config.point_x, y = config.point_y; + if( x >= 0 && x < w && y >= 0 && y < h ) + fill_region.fill(x, y); + break; + } +//crikey_pgm("/tmp/msk.pgm",msk); + + if( config.draw_mode == DRAW_MASK ) { + draw_mask(msk); + return 0; + } + + draw_alpha(msk); + return 0; +} + + +void CriKeyEngine::init_packages() +{ + int y = 0, h1 = plugin->h-1; + for(int i = 0; i < get_total_packages(); ) { + CriKeyPackage *pkg = (CriKeyPackage*)get_package(i++); + pkg->y1 = y; + y = h1 * i / LoadServer::get_total_packages(); + pkg->y2 = y; + } +} + +LoadPackage* CriKeyEngine::new_package() +{ + return new CriKeyPackage(); +} + +LoadClient* CriKeyEngine::new_client() +{ + return new CriKeyUnit(this); +} + +#define EDGE_MACRO(type, max, components, is_yuv) \ +{ \ + uint8_t **src_rows = src->get_rows(); \ + int comps = MIN(components, 3); \ + float scale = 1.0f/max; \ + for( int y=y1; yplugin->src; + int bpp = server->plugin->bpp; + VFrame *dst = server->plugin->dst; + uint8_t **dst_rows = dst->get_rows(); + float *target = server->plugin->target; + float threshold = server->plugin->config.threshold; + CriKeyPackage *pkg = (CriKeyPackage*)package; + int x1 = 0, x2 = server->plugin->w-1; + int y1 = pkg->y1, y2 = pkg->y2; + + switch( src->get_color_model() ) { + case BC_RGB_FLOAT: EDGE_MACRO(float, 1, 3, 0); + case BC_RGBA_FLOAT: EDGE_MACRO(float, 1, 4, 0); + case BC_RGB888: EDGE_MACRO(unsigned char, 0xff, 3, 0); + case BC_YUV888: EDGE_MACRO(unsigned char, 0xff, 3, 1); + case BC_RGBA8888: EDGE_MACRO(unsigned char, 0xff, 4, 0); + case BC_YUVA8888: EDGE_MACRO(unsigned char, 0xff, 4, 1); + } +} + diff --git a/cinelerra-5.1/plugins/crikey/crikey.h b/cinelerra-5.1/plugins/crikey/crikey.h new file mode 100644 index 00000000..3b8c1cfc --- /dev/null +++ b/cinelerra-5.1/plugins/crikey/crikey.h @@ -0,0 +1,130 @@ +/* + * CINELERRA + * Copyright (C) 1997-2014 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 + * + */ + + + +#ifndef EDGE_H +#define EDGE_H + +#include "loadbalance.h" +#include "pluginvclient.h" + +class CriKeyEngine; +class CriKey; + +#define DRAW_ALPHA 0 +#define DRAW_EDGE 1 +#define DRAW_MASK 2 +#define DRAW_MODES 3 + +#define KEY_SEARCH 0 +#define KEY_SEARCH_ALL 1 +#define KEY_POINT 2 +#define KEY_MODES 3 + +class CriKeyConfig +{ +public: + CriKeyConfig(); + + int equivalent(CriKeyConfig &that); + void copy_from(CriKeyConfig &that); + void interpolate(CriKeyConfig &prev, CriKeyConfig &next, + long prev_frame, long next_frame, long current_frame); + void limits(); + static void set_target(int is_yuv, int color, float *target); + static void set_color(int is_yuv, float *target, int &color); + + int color; + float threshold; + int draw_mode, key_mode; + float point_x, point_y; + int drag; +}; + +class CriKeyPackage : public LoadPackage +{ +public: + CriKeyPackage() : LoadPackage() {} + int y1, y2; +}; + +class CriKeyEngine : public LoadServer +{ +public: + CriKeyEngine(CriKey *plugin, int total_clients, int total_packages) + : LoadServer(total_clients, total_packages) { this->plugin = plugin; } + ~CriKeyEngine() {} + + void init_packages(); + LoadPackage* new_package(); + LoadClient* new_client(); + + CriKey *plugin; +}; + +class CriKeyUnit : public LoadClient +{ +public: + CriKeyUnit(CriKeyEngine *server) + : LoadClient(server) { this->server = server; } + ~CriKeyUnit() {} + + float edge_detect(float *data, float max, int do_max); + void process_package(LoadPackage *package); + CriKeyEngine *server; +}; + + +class CriKey : public PluginVClient +{ +public: + CriKey(PluginServer *server); + ~CriKey(); +// required for all realtime plugins + PLUGIN_CLASS_MEMBERS2(CriKeyConfig) + int is_realtime(); + void update_gui(); + void save_data(KeyFrame *keyframe); + void read_data(KeyFrame *keyframe); + int process_buffer(VFrame *frame, int64_t start_position, double frame_rate); + void draw_alpha(VFrame *msk); + void draw_mask(VFrame *msk); + float diff_uint8(uint8_t *tp); + float diff_float(uint8_t *tp); + float (CriKey::*diff_pixel)(uint8_t *dp); + void min_key(int &ix, int &iy); + bool find_key(int &ix, int &iy, float threshold); + static void set_target(int is_yuv, int color, float *target) { + CriKeyConfig::set_target(is_yuv, color, target); + } + static void set_color(int is_yuv, float *target, int &color) { + CriKeyConfig::set_color(is_yuv, target, color); + } + + CriKeyEngine *engine; + VFrame *src, *dst, *msk; + int w, h, color_model, bpp, comp, is_yuv, is_float; + + void get_color(int x, int y); + float target[3]; +}; + +#endif diff --git a/cinelerra-5.1/plugins/crikey/crikeywindow.C b/cinelerra-5.1/plugins/crikey/crikeywindow.C new file mode 100644 index 00000000..f8fcd1ff --- /dev/null +++ b/cinelerra-5.1/plugins/crikey/crikeywindow.C @@ -0,0 +1,360 @@ +/* + * CINELERRA + * Copyright (C) 2014 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 "automation.h" +#include "bcdisplayinfo.h" +#include "clip.h" +#include "crikey.h" +#include "crikeywindow.h" +#include "cwindow.h" +#include "cwindowgui.h" +#include "edl.h" +#include "edlsession.h" +#include "language.h" +#include "mwindow.h" +#include "plugin.h" +#include "pluginserver.h" +#include "theme.h" +#include "track.h" + +#define COLOR_W 50 +#define COLOR_H 30 + +CriKeyNum::CriKeyNum(CriKeyWindow *gui, int x, int y, float &output) + : BC_TumbleTextBox(gui, output, -32767.0f, 32767.0f, x, y, 80) +{ + this->gui = gui; + this->output = &output; + set_increment(1); + set_precision(1); +} + +CriKeyNum::~CriKeyNum() +{ +} + +int CriKeyNum::handle_event() +{ + *output = atof(get_text()); + gui->plugin->send_configure_change(); + return 1; +} + +int CriKeyDrawModeItem::handle_event() +{ + ((CriKeyDrawMode *)get_popup_menu())->update(id); + return 1; +} +CriKeyDrawMode::CriKeyDrawMode(CriKeyWindow *gui, int x, int y) + : BC_PopupMenu(x, y, 100, "", 1) +{ + this->gui = gui; + draw_modes[DRAW_ALPHA] = _("Alpha"); + draw_modes[DRAW_EDGE] = _("Edge"); + draw_modes[DRAW_MASK] = _("Mask"); + mode = -1; +} +void CriKeyDrawMode::create_objects() +{ + for( int i=0; iplugin->config.draw_mode); +} +void CriKeyDrawMode::update(int mode) +{ + if( this->mode == mode ) return; + this->mode = mode; + set_text(draw_modes[mode]); + gui->plugin->config.draw_mode = mode; + gui->plugin->send_configure_change(); +} + +int CriKeyKeyModeItem::handle_event() +{ + ((CriKeyKeyMode *)get_popup_menu())->update(id); + return 1; +} +CriKeyKeyMode::CriKeyKeyMode(CriKeyWindow *gui, int x, int y) + : BC_PopupMenu(x, y, 100, "", 1) +{ + this->gui = gui; + key_modes[KEY_SEARCH] = _("Search"); + key_modes[KEY_SEARCH_ALL] = _("Search all"); + key_modes[KEY_POINT] = _("Point"); + this->mode = -1; +} +void CriKeyKeyMode::create_objects() +{ + for( int i=0; iplugin->config.key_mode); +} +void CriKeyKeyMode::update(int mode) +{ + if( this->mode == mode ) return; + this->mode = mode; + set_text(key_modes[mode]); + gui->draw_key(mode); + gui->plugin->send_configure_change(); +} + +CriKeyColorButton::CriKeyColorButton(CriKeyWindow *gui, int x, int y) + : BC_GenericButton(x, y, _("Color")) +{ + this->gui = gui; +} +int CriKeyColorButton::handle_event() +{ + gui->start_color_thread(); + return 1; +} + +CriKeyColorPicker::CriKeyColorPicker(CriKeyColorButton *color_button) + : ColorPicker(0, _("Color")) +{ + this->color_button = color_button; +} + +void CriKeyColorPicker::start(int color) +{ + start_window(this->color = color, 0, 1); +} + +void CriKeyColorPicker::handle_done_event(int result) +{ + if( !result ) { + CriKeyWindow *gui = color_button->gui; + gui->lock_window("CriKeyColorPicker::handle_done_event"); + gui->update_color(color); + gui->plugin->config.color = color; + gui->plugin->send_configure_change(); + gui->unlock_window(); + } +} + +int CriKeyColorPicker::handle_new_color(int color, int alpha) +{ + CriKeyWindow *gui = color_button->gui; + gui->lock_window("CriKeyColorPicker::handle_new_color"); + gui->update_color(this->color = color); + gui->flush(); + gui->unlock_window(); + return 1; +} + + +void CriKeyWindow::start_color_thread() +{ + unlock_window(); + delete color_picker; + color_picker = new CriKeyColorPicker(color_button); + color_picker->start(plugin->config.color); + lock_window("CriKeyWindow::start_color_thread"); +} + + +CriKeyWindow::CriKeyWindow(CriKey *plugin) + : PluginClientWindow(plugin, 320, 220, 320, 220, 0) +{ + this->plugin = plugin; + this->color_button = 0; + this->color_picker = 0; + this->title_x = 0; this->point_x = 0; + this->title_y = 0; this->point_y = 0; + this->dragging = 0; this->drag = 0; +} + +CriKeyWindow::~CriKeyWindow() +{ + delete color_picker; +} + +void CriKeyWindow::create_objects() +{ + int x = 10, y = 10; + int margin = plugin->get_theme()->widget_border; + BC_Title *title; + add_subwindow(title = new BC_Title(x, y, _("Threshold:"))); + y += title->get_h() + margin; + add_subwindow(threshold = new CriKeyThreshold(this, x, y, get_w() - x * 2)); + y += threshold->get_h() + margin; + add_subwindow(title = new BC_Title(x, y+5, _("Draw mode:"))); + int x1 = x + title->get_w() + 10 + margin; + add_subwindow(draw_mode = new CriKeyDrawMode(this, x1, y)); + draw_mode->create_objects(); + y += draw_mode->get_h() + margin; + add_subwindow(title = new BC_Title(x, y+5, _("Key mode:"))); + add_subwindow(key_mode = new CriKeyKeyMode(this, x1, y)); + y += key_mode->get_h() + margin; + key_x = x + 10 + margin; key_y = y + 10 + margin; + key_mode->create_objects(); + + if( plugin->config.drag ) + grab(plugin->server->mwindow->cwindow->gui); + show_window(1); +} + +int CriKeyWindow::grab_event(XEvent *event) +{ + if( key_mode->mode != KEY_POINT ) return 0; + + switch( event->type ) { + case ButtonPress: + if( dragging ) return 0; + dragging = 1; + break; + case ButtonRelease: + if( !dragging ) return 0; + dragging = 0; + return 1; + case MotionNotify: + if( dragging ) break; + default: + return 0; + } + MWindow *mwindow = plugin->server->mwindow; + CWindowGUI *cwindow_gui = mwindow->cwindow->gui; + CWindowCanvas *canvas = cwindow_gui->canvas; + float cursor_x = canvas->get_canvas()->get_relative_cursor_x(); + float cursor_y = canvas->get_canvas()->get_relative_cursor_y(); + canvas->canvas_to_output(mwindow->edl, 0, cursor_x, cursor_y); + int64_t position = plugin->get_source_position(); + float projector_x, projector_y, projector_z; + Track *track = plugin->server->plugin->track; + int track_w = track->track_w, track_h = track->track_h; + track->automation->get_projector( + &projector_x, &projector_y, &projector_z, + position, PLAY_FORWARD); + projector_x += mwindow->edl->session->output_w / 2; + projector_y += mwindow->edl->session->output_h / 2; + float output_x = (cursor_x - projector_x) / projector_z + track_w / 2; + float output_y = (cursor_y - projector_y) / projector_z + track_h / 2; + point_x->update((int64_t)(plugin->config.point_x = output_x)); + point_y->update((int64_t)(plugin->config.point_y = output_y)); + plugin->send_configure_change(); + return 1; +} + +void CriKeyWindow::done_event(int result) +{ + ungrab(client->server->mwindow->cwindow->gui); + if( color_picker ) color_picker->close_window(); +} + +void CriKeyWindow::draw_key(int mode) +{ + int margin = plugin->get_theme()->widget_border; + int x = key_x, y = key_y; + delete color_picker; color_picker = 0; + delete color_button; color_button = 0; + delete title_x; title_x = 0; + delete point_x; point_x = 0; + delete title_y; title_y = 0; + delete point_y; point_y = 0; + delete drag; drag = 0; + + clear_box(x,y, get_w()-x,get_h()-y); + flash(x,y, get_w()-x,get_h()-y); + + switch( mode ) { + case KEY_SEARCH: + case KEY_SEARCH_ALL: + add_subwindow(color_button = new CriKeyColorButton(this, x, y)); + x += color_button->get_w() + margin; + color_x = x; color_y = y; + update_color(plugin->config.color); + break; + case KEY_POINT: + add_subwindow(title_x = new BC_Title(x, y, _("X:"))); + int x1 = x + title_x->get_w() + margin, y1 = y; + point_x = new CriKeyNum(this, x1, y, plugin->config.point_x); + point_x->create_objects(); + y += point_x->get_h() + margin; + add_subwindow(title_y = new BC_Title(x, y, _("Y:"))); + point_y = new CriKeyNum(this, x1, y, plugin->config.point_y); + point_y->create_objects(); + x1 += point_x->get_w() + margin; + add_subwindow(drag = new CriKeyDrag(this, x1, y1)); + break; + } + plugin->config.key_mode = mode; + show_window(1); +} + +void CriKeyWindow::update_color(int color) +{ + set_color(color); + draw_box(color_x, color_y, COLOR_W, COLOR_H); + set_color(BLACK); + draw_rectangle(color_x, color_y, COLOR_W, COLOR_H); + flash(color_x, color_y, COLOR_W, COLOR_H); +} + +void CriKeyWindow::update_gui() +{ + threshold->update(plugin->config.threshold); + draw_mode->update(plugin->config.draw_mode); + key_mode->update(plugin->config.key_mode); + switch( plugin->config.key_mode ) { + case KEY_POINT: + point_x->update(plugin->config.point_x); + point_y->update(plugin->config.point_y); + break; + case KEY_SEARCH: + case KEY_SEARCH_ALL: + update_color(plugin->config.color); + break; + } +} + + +CriKeyThreshold::CriKeyThreshold(CriKeyWindow *gui, int x, int y, int w) + : BC_FSlider(x, y, 0, w, w, 0, 1, gui->plugin->config.threshold, 0) +{ + this->gui = gui; + set_precision(0.005); +} + +int CriKeyThreshold::handle_event() +{ + gui->plugin->config.threshold = get_value(); + gui->plugin->send_configure_change(); + return 1; +} + + +CriKeyDrag::CriKeyDrag(CriKeyWindow *gui, int x, int y) + : BC_CheckBox(x, y, gui->plugin->config.drag, _("Drag")) +{ + this->gui = gui; +} +int CriKeyDrag::handle_event() +{ + int value = get_value(); + gui->plugin->config.drag = value; + CWindowGUI *cwindow_gui = gui->plugin->server->mwindow->cwindow->gui; + if( value ) + gui->grab(cwindow_gui); + else + gui->ungrab(cwindow_gui); + gui->plugin->send_configure_change(); + return 1; +} + diff --git a/cinelerra-5.1/plugins/crikey/crikeywindow.h b/cinelerra-5.1/plugins/crikey/crikeywindow.h new file mode 100644 index 00000000..0814abaf --- /dev/null +++ b/cinelerra-5.1/plugins/crikey/crikeywindow.h @@ -0,0 +1,161 @@ +/* + * CINELERRA + * Copyright (C) 2008-2015 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 + * + */ + +#ifndef __CRIKEYWINDOW_H__ +#define __CRIKEYWINDOW_H__ + +#include "guicast.h" +#include "colorpicker.h" + +class CriKey; +class CriKeyWindow; +class CriKeyNum; +class CriKeyColorButton; +class CriKeyColorPicker; +class CriKeyDrawMode; +class CriKeyDrawModeItem; +class CriKeyKeyMode; +class CriKeyKeyModeItem; +class CriKeyThreshold; + +class CriKeyNum : public BC_TumbleTextBox +{ +public: + CriKeyWindow *gui; + float *output; + int handle_event(); + + CriKeyNum(CriKeyWindow *gui, int x, int y, float &output); + ~CriKeyNum(); +}; + +class CriKeyColorButton : public BC_GenericButton +{ +public: + CriKeyColorButton(CriKeyWindow *gui, int x, int y); + + int handle_event(); + CriKeyWindow *gui; +}; + +class CriKeyColorPicker : public ColorPicker +{ +public: + CriKeyColorPicker(CriKeyColorButton *color_button); + + void start(int color); + int handle_new_color(int color, int alpha); + void handle_done_event(int result); + + CriKeyColorButton *color_button; + int color; +}; + +class CriKeyDrawMode : public BC_PopupMenu +{ + const char *draw_modes[DRAW_MODES]; +public: + CriKeyDrawMode(CriKeyWindow *gui, int x, int y); + + void create_objects(); + void update(int mode); + CriKeyWindow *gui; + int mode; +}; +class CriKeyDrawModeItem : public BC_MenuItem +{ +public: + CriKeyDrawModeItem(const char *txt, int id) + : BC_MenuItem(txt) { this->id = id; } + + int handle_event(); + CriKeyWindow *gui; + int id; +}; + +class CriKeyKeyMode : public BC_PopupMenu +{ + const char *key_modes[KEY_MODES]; +public: + CriKeyKeyMode(CriKeyWindow *gui, int x, int y); + + void create_objects(); + void update(int mode); + CriKeyWindow *gui; + int mode; +}; +class CriKeyKeyModeItem : public BC_MenuItem +{ +public: + CriKeyKeyModeItem(const char *text, int id) + : BC_MenuItem(text) { this->id = id; } + + int handle_event(); + CriKeyWindow *gui; + int id; +}; + +class CriKeyThreshold : public BC_FSlider +{ +public: + CriKeyThreshold(CriKeyWindow *gui, int x, int y, int w); + int handle_event(); + CriKeyWindow *gui; +}; + +class CriKeyDrag : public BC_CheckBox +{ +public: + CriKeyDrag(CriKeyWindow *gui, int x, int y); + + int handle_event(); + CriKeyWindow *gui; +}; + +class CriKeyWindow : public PluginClientWindow +{ +public: + CriKeyWindow(CriKey *plugin); + ~CriKeyWindow(); + + void create_objects(); + void draw_key(int mode); + void update_color(int color); + void update_gui(); + void start_color_thread(); + int grab_event(XEvent *event); + void done_event(int result); + + CriKey *plugin; + CriKeyThreshold *threshold; + CriKeyDrawMode *draw_mode; + CriKeyKeyMode *key_mode; + + CriKeyColorButton *color_button; + CriKeyColorPicker *color_picker; + int color_x, color_y, key_x, key_y; + BC_Title *title_x, *title_y; + CriKeyNum *point_x, *point_y; + int dragging; + CriKeyDrag *drag; +}; + +#endif + diff --git a/cinelerra-5.1/plugins/crikey/picon.png b/cinelerra-5.1/plugins/crikey/picon.png new file mode 100644 index 0000000000000000000000000000000000000000..364b15480f757b8239583edd43ad5d1f3529d22d GIT binary patch literal 3155 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 literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/plugins/edge/edge.C b/cinelerra-5.1/plugins/edge/edge.C index 45172ae8..b0c14ea9 100644 --- a/cinelerra-5.1/plugins/edge/edge.C +++ b/cinelerra-5.1/plugins/edge/edge.C @@ -28,8 +28,6 @@ #include "transportque.inc" #include -// Edge detection from the Gimp - REGISTER_PLUGIN(Edge) EdgeConfig::EdgeConfig() @@ -48,12 +46,8 @@ void EdgeConfig::copy_from(EdgeConfig &that) this->amount = that.amount; } -void EdgeConfig::interpolate( - EdgeConfig &prev, - EdgeConfig &next, - long prev_frame, - long next_frame, - long current_frame) +void EdgeConfig::interpolate( EdgeConfig &prev, EdgeConfig &next, + long prev_frame, long next_frame, long current_frame) { copy_from(next); } @@ -68,13 +62,13 @@ Edge::Edge(PluginServer *server) : PluginVClient(server) { engine = 0; - temp = 0; + dst = 0; } Edge::~Edge() { - if(engine) delete engine; - if(temp) delete temp; + delete engine; + delete dst; } const char* Edge::plugin_title() { return _("Edge"); } @@ -103,27 +97,16 @@ void Edge::save_data(KeyFrame *keyframe) void Edge::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("EDGE")) - { - config.amount = input.tag.get_property("AMOUNT", config.amount); - config.limits(); - - } - else - if(input.tag.title_is("/EDGE")) - { - result = 1; - } + + while( !(result=input.read_tag()) ) { + if(input.tag.title_is("EDGE")) { + config.amount = input.tag.get_property("AMOUNT", config.amount); + config.limits(); + } + else if(input.tag.title_is("/EDGE")) { + result = 1; } } @@ -131,61 +114,41 @@ void Edge::read_data(KeyFrame *keyframe) void Edge::update_gui() { - if(thread) - { - if(load_configuration()) - { - thread->window->lock_window("Edge::update_gui"); - EdgeWindow *window = (EdgeWindow*)thread->window; - window->flush(); - thread->window->unlock_window(); - } - } + if( !thread ) return; + if( !load_configuration() ) return; + thread->window->lock_window("Edge::update_gui"); + EdgeWindow *window = (EdgeWindow*)thread->window; + window->flush(); + thread->window->unlock_window(); } - - -int Edge::process_buffer(VFrame *frame, - int64_t start_position, - double frame_rate) +int Edge::process_buffer(VFrame *frame, int64_t start_position, double frame_rate) { - -// int need_reconfigure = load_configuration(); - int w = frame->get_w(); - int h = frame->get_h(); - int color_model = frame->get_color_model(); + src = frame; + w = src->get_w(), h = src->get_h(); + color_model = frame->get_color_model(); + bpp = BC_CModels::calculate_pixelsize(color_model); + + if( dst && (dst->get_w() != w || dst->get_h() != h || + dst->get_color_model() != color_model ) ) { + delete dst; dst = 0; + } + if( !dst ) + dst = new VFrame(0, -1, w, h, color_model, -1); -// initialize everything - if(!temp) - { + if( !engine ) engine = new EdgeEngine(this, PluginClient::get_project_smp() + 1, PluginClient::get_project_smp() + 1); - temp = new VFrame(0, - -1, - w, - h, - color_model, - -1); - - } - - read_frame(frame, - 0, - start_position, - frame_rate, - 0); - engine->process(temp, frame); - frame->copy_from(temp); - + read_frame(frame, 0, start_position, frame_rate, 0); + engine->process_packages(); + frame->copy_from(dst); return 0; } - - EdgePackage::EdgePackage() : LoadPackage() { @@ -200,143 +163,60 @@ EdgeUnit::~EdgeUnit() { } - -float EdgeUnit::edge_detect(float *data, float max, int do_max) -{ - const float v_kernel[9] = { 0, 0, 0, - 0, 2, -2, - 0, 2, -2 }; - const float h_kernel[9] = { 0, 0, 0, - 0, -2, -2, - 0, 2, 2 }; - int i; - float v_grad, h_grad; - float amount = server->plugin->config.amount; - - for (i = 0, v_grad = 0, h_grad = 0; i < 9; i++) - { - v_grad += v_kernel[i] * data[i]; - h_grad += h_kernel[i] * data[i]; - } - - float result = sqrt (v_grad * v_grad * amount + - h_grad * h_grad * amount); - if(do_max) - CLAMP(result, 0, max); - return result; -} - #define EDGE_MACRO(type, max, components, is_yuv) \ { \ - type **input_rows = (type**)server->src->get_rows(); \ - type **output_rows = (type**)server->dst->get_rows(); \ int comps = MIN(components, 3); \ - for(int y = pkg->y1; y < pkg->y2; y++) \ - { \ - for(int x = 0; x < w; x++) \ - { \ -/* kernel is in bounds */ \ - if(y > 0 && x > 0 && y < h - 2 && x < w - 2) \ - { \ - for(int chan = 0; chan < comps; chan++) \ - { \ -/* load kernel */ \ - for(int kernel_y = 0; kernel_y < 3; kernel_y++) \ - { \ - for(int kernel_x = 0; kernel_x < 3; kernel_x++) \ - { \ - kernel[3 * kernel_y + kernel_x] = \ - (type)input_rows[y - 1 + kernel_y][(x - 1 + kernel_x) * components + chan]; \ - \ - if(is_yuv && chan > 0) \ - { \ - kernel[3 * kernel_y + kernel_x] -= 0x80; \ - } \ - \ - } \ - } \ -/* do the business */ \ - output_rows[y][x * components + chan] = edge_detect(kernel, max, sizeof(type) < 4); \ - if(is_yuv && chan > 0) \ - { \ - output_rows[y][x * components + chan] += 0x80; \ - } \ - \ - } \ - \ - if(components == 4) output_rows[y][x * components + 3] = \ - input_rows[y][x * components + 3]; \ + float amounts = amount * amount / max; \ + for( int y=y1; y h_grad ) h_grad = dh; \ + float dv = r0[0] - r0[components] + r1[0] - r1[components]; \ + if( (dv*=dv) > v_grad ) v_grad = dv; \ } \ - else \ - { \ - for(int chan = 0; chan < comps; chan++) \ - { \ -/* load kernel */ \ - for(int kernel_y = 0; kernel_y < 3; kernel_y++) \ - { \ - for(int kernel_x = 0; kernel_x < 3; kernel_x++) \ - { \ - int in_y = y - 1 + kernel_y; \ - int in_x = x - 1 + kernel_x; \ - CLAMP(in_y, 0, h - 1); \ - CLAMP(in_x, 0, w - 1); \ - kernel[3 * kernel_y + kernel_x] = \ - (type)input_rows[in_y][in_x * components + chan]; \ - if(is_yuv && chan > 0) \ - { \ - kernel[3 * kernel_y + kernel_x] -= 0x80; \ - } \ - } \ - } \ -/* do the business */ \ - output_rows[y][x * components + chan] = edge_detect(kernel, max, sizeof(type) < 4); \ - if(is_yuv && chan > 0) \ - { \ - output_rows[y][x * components + chan] += 0x80; \ - } \ - } \ - if(components == 4) output_rows[y][x * components + 3] = \ - input_rows[y][x * components + 3]; \ + float v = (h_grad + v_grad) * amounts; \ + type t = v > max ? max : v; \ + if( is_yuv ) { \ + *op++ = t; *op++ = 0x80; *op++ = 0x80; \ } \ + else { \ + for( int i=0; iplugin->src; + uint8_t **input_rows = src->get_rows(); + VFrame *dst = server->plugin->dst; + uint8_t **output_rows = dst->get_rows(); + float amount = (float)server->plugin->config.amount; EdgePackage *pkg = (EdgePackage*)package; - int w = server->src->get_w(); - int h = server->src->get_h(); - float kernel[9]; - - switch(server->src->get_color_model()) - { - case BC_RGB_FLOAT: - EDGE_MACRO(float, 1, 3, 0); - break; - case BC_RGBA_FLOAT: - EDGE_MACRO(float, 1, 4, 0); - break; - case BC_RGB888: - EDGE_MACRO(unsigned char, 0xff, 3, 0); - break; - case BC_YUV888: - EDGE_MACRO(unsigned char, 0xff, 3, 1); - break; - case BC_RGBA8888: - EDGE_MACRO(unsigned char, 0xff, 4, 0); - break; - case BC_YUVA8888: - EDGE_MACRO(unsigned char, 0xff, 4, 1); - break; + int x1 = 0, x2 = server->plugin->w-1, bpp = server->plugin->bpp; + int y1 = pkg->y1, y2 = pkg->y2; + + switch( server->plugin->color_model ) { + case BC_RGB_FLOAT: EDGE_MACRO(float, 1, 3, 0); + case BC_RGBA_FLOAT: EDGE_MACRO(float, 1, 4, 0); + case BC_RGB888: EDGE_MACRO(unsigned char, 0xff, 3, 0); + case BC_YUV888: EDGE_MACRO(unsigned char, 0xff, 3, 1); + case BC_RGBA8888: EDGE_MACRO(unsigned char, 0xff, 4, 0); + case BC_YUVA8888: EDGE_MACRO(unsigned char, 0xff, 4, 1); } } -EdgeEngine::EdgeEngine(Edge *plugin, - int total_clients, - int total_packages) +EdgeEngine::EdgeEngine(Edge *plugin, int total_clients, int total_packages) : LoadServer(total_clients, total_packages) { this->plugin = plugin; @@ -349,22 +229,15 @@ EdgeEngine::~EdgeEngine() void EdgeEngine::init_packages() { - for(int i = 0; i < get_total_packages(); i++) - { - EdgePackage *pkg = (EdgePackage*)get_package(i); - pkg->y1 = plugin->get_input(0)->get_h() * i / LoadServer::get_total_packages(); - pkg->y2 = plugin->get_input(0)->get_h() * (i + 1) / LoadServer::get_total_packages(); + int y = 0, h1 = plugin->h-1; + for(int i = 0; i < get_total_packages(); ) { + EdgePackage *pkg = (EdgePackage*)get_package(i++); + pkg->y1 = y; + y = h1 * i / LoadServer::get_total_packages(); + pkg->y2 = y; } } -void EdgeEngine::process(VFrame *dst, VFrame *src) -{ - this->dst = dst; - this->src = src; - process_packages(); -} - - LoadClient* EdgeEngine::new_client() { return new EdgeUnit(this); @@ -375,4 +248,3 @@ LoadPackage* EdgeEngine::new_package() return new EdgePackage; } - diff --git a/cinelerra-5.1/plugins/edge/edge.h b/cinelerra-5.1/plugins/edge/edge.h index 6211fda6..5fddd982 100644 --- a/cinelerra-5.1/plugins/edge/edge.h +++ b/cinelerra-5.1/plugins/edge/edge.h @@ -36,14 +36,10 @@ public: int equivalent(EdgeConfig &that); void copy_from(EdgeConfig &that); - void interpolate(EdgeConfig &prev, - EdgeConfig &next, - long prev_frame, - long next_frame, - long current_frame); + void interpolate(EdgeConfig &prev, EdgeConfig &next, + long prev_frame, long next_frame, long current_frame); void limits(); - int amount; }; @@ -51,8 +47,7 @@ class EdgePackage : public LoadPackage { public: EdgePackage(); - int y1; - int y2; + int y1, y2; }; class EdgeUnit : public LoadClient @@ -75,11 +70,9 @@ public: ~EdgeEngine(); void init_packages(); - void process(VFrame *dst, VFrame *src); LoadClient* new_client(); LoadPackage* new_package(); - VFrame *src, *dst; Edge *plugin; }; @@ -100,12 +93,8 @@ public: double frame_rate); EdgeEngine *engine; - VFrame *temp; + VFrame *src, *dst; + int w, h, color_model, bpp; }; - - #endif - - - -- 2.26.2