From 1c43268ae0d6d6fad8beff33946e1115a8ec34b2 Mon Sep 17 00:00:00 2001 From: Good Guy Date: Wed, 21 Mar 2018 15:51:04 -0600 Subject: [PATCH] add descratch plugin, single frame silence insert, docs --- cinelerra-5.1/cinelerra/mwindowedit.C | 4 + cinelerra-5.1/doc/shortcuts.html | 2 +- cinelerra-5.1/plugin_defs | 2 +- cinelerra-5.1/plugins/Makefile | 1 + cinelerra-5.1/plugins/descratch/Makefile | 9 + cinelerra-5.1/plugins/descratch/descratch.C | 725 ++++++++++++++++++++ cinelerra-5.1/plugins/descratch/descratch.h | 187 +++++ 7 files changed, 928 insertions(+), 2 deletions(-) create mode 100644 cinelerra-5.1/plugins/descratch/Makefile create mode 100644 cinelerra-5.1/plugins/descratch/descratch.C create mode 100644 cinelerra-5.1/plugins/descratch/descratch.h diff --git a/cinelerra-5.1/cinelerra/mwindowedit.C b/cinelerra-5.1/cinelerra/mwindowedit.C index ca3475ed..142c2a38 100644 --- a/cinelerra-5.1/cinelerra/mwindowedit.C +++ b/cinelerra-5.1/cinelerra/mwindowedit.C @@ -1600,6 +1600,10 @@ void MWindow::paste_silence() { double start = edl->local_session->get_selectionstart(); double end = edl->local_session->get_selectionend(); + if( EQUIV(start, end) ) { + if( edl->session->frame_rate > 0 ) + end += 1./edl->session->frame_rate; + } undo->update_undo_before(); edl->paste_silence(start, end, edl->session->labels_follow_edits, diff --git a/cinelerra-5.1/doc/shortcuts.html b/cinelerra-5.1/doc/shortcuts.html index 15a65cc7..f6f173b8 100644 --- a/cinelerra-5.1/doc/shortcuts.html +++ b/cinelerra-5.1/doc/shortcuts.html @@ -190,7 +190,7 @@
Paste Silence 'Shift-Space' - Paste empty edit + Paste empty edit at selection or frame if none
diff --git a/cinelerra-5.1/plugin_defs b/cinelerra-5.1/plugin_defs index 2d4690ea..ecf3dc9b 100644 --- a/cinelerra-5.1/plugin_defs +++ b/cinelerra-5.1/plugin_defs @@ -40,7 +40,7 @@ video_tools := blur decimate delayvideo denoisemjpeg denoisevideo downsample \ motion2 motionblur motion motion-cv motion-hv motion51 \ overlay radialblur reframe reframert reroute reversevideo \ rumbler seltempavg sharpen svg titler timeavg timefront \ - unsharp videoscope wave zoomblur findobject + unsharp videoscope wave zoomblur findobject descratch plugin_dirs += blending blending := crikey chromakeyhsv chromakey diffkey diff --git a/cinelerra-5.1/plugins/Makefile b/cinelerra-5.1/plugins/Makefile index a492ca86..e86526ab 100644 --- a/cinelerra-5.1/plugins/Makefile +++ b/cinelerra-5.1/plugins/Makefile @@ -49,6 +49,7 @@ DIRS = $(OPENCV_OBJS) \ denoisefft \ denoiseseltempavg \ denoisevideo \ + descratch \ despike \ diffkey \ dissolve \ diff --git a/cinelerra-5.1/plugins/descratch/Makefile b/cinelerra-5.1/plugins/descratch/Makefile new file mode 100644 index 00000000..3de4ca12 --- /dev/null +++ b/cinelerra-5.1/plugins/descratch/Makefile @@ -0,0 +1,9 @@ +include ../../plugin_defs + +OBJS = $(OBJDIR)/descratch.o + +PLUGIN = descratch + +include ../../plugin_config + +$(OBJDIR)/descratch.o: descratch.C diff --git a/cinelerra-5.1/plugins/descratch/descratch.C b/cinelerra-5.1/plugins/descratch/descratch.C new file mode 100644 index 00000000..8375510f --- /dev/null +++ b/cinelerra-5.1/plugins/descratch/descratch.C @@ -0,0 +1,725 @@ +/* +DeScratch - Scratches Removing Filter +Plugin for Avisynth 2.5 +Copyright (c)2003-2016 Alexander G. Balakhnin aka Fizick +bag@hotmail.ru http://avisynth.org.ru + +This program is FREE software under GPL licence v2. + +This plugin removes vertical scratches from digitized films. +Reworked for cin5 by GG. 03/2018, from the laws of Fizick's +*/ + + +#include "clip.h" +#include "filexml.h" +#include "language.h" +#include "descratch.h" + +REGISTER_PLUGIN(DeScratchMain) + +DeScratchMain::DeScratchMain(PluginServer *server) + : PluginVClient(server) +{ + inf = 0; sz_inf = 0; + src = 0; dst = 0; + tmp_frame = 0; + blurry = 0; + overlay_frame = 0; +} + +DeScratchMain::~DeScratchMain() +{ + delete [] inf; + delete src; + delete dst; + delete blurry; + delete tmp_frame; + delete overlay_frame; +} + +const char* DeScratchMain::plugin_title() { return N_("DeScratch"); } +int DeScratchMain::is_realtime() { return 1; } + +void DeScratchConfig::reset() +{ + threshold = 24; + asymmetry = 16; + min_width = 1; + max_width = 3; + min_len = 1; + max_len = 100; + max_angle = 45; + blur_len = 4; + gap_len = 10; + mode_y = MODE_ALL; + mode_u = MODE_NONE; + mode_v = MODE_NONE; + mark = 0; + ffade = 100; + border = 2; +} + +DeScratchConfig::DeScratchConfig() +{ + reset(); +} + +DeScratchConfig::~DeScratchConfig() +{ +} + +int DeScratchConfig::equivalent(DeScratchConfig &that) +{ + return threshold == that.threshold && + asymmetry == that.asymmetry && + min_width == that.min_width && + max_width == that.max_width && + min_len == that.min_len && + max_len == that.max_len && + max_angle == that.max_angle && + blur_len == that.blur_len && + gap_len == that.gap_len && + mode_y == that.mode_y && + mode_u == that.mode_u && + mode_v == that.mode_v && + mark == that.mark && + ffade == that.ffade && + border == that.border; +} +void DeScratchConfig::copy_from(DeScratchConfig &that) +{ + threshold = that.threshold; + asymmetry = that.asymmetry; + min_width = that.min_width; + max_width = that.max_width; + min_len = that.min_len; + max_len = that.max_len; + max_angle = that.max_angle; + blur_len = that.blur_len; + gap_len = that.gap_len; + mode_y = that.mode_y; + mode_u = that.mode_u; + mode_v = that.mode_v; + mark = that.mark; + ffade = that.ffade; + border = that.border; +} + +void DeScratchConfig::interpolate(DeScratchConfig &prev, DeScratchConfig &next, + int64_t prev_frame, int64_t next_frame, int64_t current_frame) +{ + copy_from(prev); +} + +LOAD_CONFIGURATION_MACRO(DeScratchMain, DeScratchConfig) + +void DeScratchMain::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("DESCRATCH"); + output.tag.set_property("THRESHOLD", config.threshold); + output.tag.set_property("ASYMMETRY", config.asymmetry); + output.tag.set_property("MIN_WIDTH", config.min_width); + output.tag.set_property("MAX_WIDTH", config.max_width); + output.tag.set_property("MIN_LEN", config.min_len); + output.tag.set_property("MAX_LEN", config.max_len); + output.tag.set_property("MAX_ANGLE", config.max_angle); + output.tag.set_property("BLUR_LEN", config.blur_len); + output.tag.set_property("GAP_LEN", config.gap_len); + output.tag.set_property("MODE_Y", config.mode_y); + output.tag.set_property("MODE_U", config.mode_u); + output.tag.set_property("MODE_V", config.mode_v); + output.tag.set_property("MARK", config.mark); + output.tag.set_property("FFADE", config.ffade); + output.tag.set_property("BORDER", config.border); + output.append_tag(); + output.tag.set_title("/DESCRATCH"); + output.append_tag(); + output.append_newline(); + output.terminate_string(); +} + +void DeScratchMain::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("DESCRATCH")) { + config.threshold = input.tag.get_property("THRESHOLD", config.threshold); + config.asymmetry = input.tag.get_property("ASYMMETRY", config.asymmetry); + config.min_width = input.tag.get_property("MIN_WIDTH", config.min_width); + config.max_width = input.tag.get_property("MAX_WIDTH", config.max_width); + config.min_len = input.tag.get_property("MIN_LEN", config.min_len); + config.max_len = input.tag.get_property("MAX_LEN", config.max_len); + config.max_angle = input.tag.get_property("MAX_ANGLE", config.max_angle); + config.blur_len = input.tag.get_property("BLUR_LEN", config.blur_len); + config.gap_len = input.tag.get_property("GAP_LEN", config.gap_len); + config.mode_y = input.tag.get_property("MODE_Y", config.mode_y); + config.mode_u = input.tag.get_property("MODE_U", config.mode_u); + config.mode_v = input.tag.get_property("MODE_V", config.mode_v); + config.mark = input.tag.get_property("MARK", config.mark); + config.ffade = input.tag.get_property("FFADE", config.ffade); + config.border = input.tag.get_property("BORDER", config.border); + } + } +} + +void DeScratchMain::get_extrems_plane(int comp, int thresh) +{ + uint8_t **rows = blurry->get_rows(); + int d = config.max_width, d1 = d+1, wd = src_w - d1; + int bpp = 3, dsz = d * bpp; + int asym = config.asymmetry; + if( thresh > 0 ) { // black (low value) scratches + for( int y=0; y thresh && (rp[0]-*dp) > thresh && + (abs(lp[-bpp]-rp[+bpp]) <= asym) && + ((lp[0]-lp[+bpp]) + (rp[0]-rp[-bpp]) > + (lp[-bpp]-lp[0]) + (rp[bpp]-rp[0])) ? + SD_EXTREM : SD_NULL; // sharp extremum found + } + for( ; xget_rows(); + int d = config.min_width, d1 = d+1, wd = src_w - d1; + int bpp = 3, dsz = d * bpp; + int asym = config.asymmetry; + if( thresh > 0 ) { // black (low value) scratches + for( int y=0; y thresh && (rp[0]-*dp) > thresh && + (abs(lp[-bpp]-rp[+bpp]) <= asym) && + ((lp[0]-lp[+bpp]) + (rp[0]-rp[-bpp]) > + (lp[-bpp]-lp[0]) + (rp[bpp]-rp[0])) ) + *ip = SD_NULL; // sharp extremum found + } + } + } + else { // white (high value) scratches + for( int y=0; y0; ) *(bp-=src_w) = SD_EXTREM; + } + } +} + +void DeScratchMain::test_scratches() +{ + int w2 = src_w - 2; + int min_len = config.min_len * src_h / 100; + int max_len = config.max_len * src_h / 100; + int maxwidth = config.max_width*2 + 1; + int maxangle = config.max_angle; + + for( int y=0; y= 3 ) { + if( ip[-2] == SD_EXTREM ) { ip[-2] = SD_TESTED; nctr = ctr-2; ++n; } + if( ip[+2] == SD_EXTREM ) { ip[+2] = SD_TESTED; nctr = ctr+2; ++n; } + } + if( ip[-1] == SD_EXTREM ) { ip[-1] = SD_TESTED; nctr = ctr-1; ++n; } + if( ip[+1] == SD_EXTREM ) { ip[+1] = SD_TESTED; nctr = ctr+1; ++n; } + if( ip[+0] == SD_EXTREM ) { ip[+0] = SD_TESTED; nctr = ctr+0; ++n; } + // end of points tests, check result for row: + // check gap and angle, if no points or big angle, it is end of inf + if( !n || abs(nctr%src_w - x) >= maxwidth+len*maxangle/57 ) break; + ctr = nctr + src_w; // new center for next row test + } + int mask = len >= min_len && len <= max_len ? SD_GOOD : SD_REJECT; + ctr = ofs+1; nctr = ctr; // pass2 + for( len=0; len= 3 ) { + if( ip[-2] == SD_TESTED ) { ip[-2] = mask; nctr = ctr-2; ++n; } + if( ip[+2] == SD_TESTED ) { ip[+2] = mask; nctr = ctr+2; ++n; } + } + if( ip[-1] == SD_TESTED ) { ip[-1] = mask; nctr = ctr-1; ++n; } + if( ip[+1] == SD_TESTED ) { ip[+1] = mask; nctr = ctr+1; ++n; } + if( ip[+0] == SD_TESTED ) { ip[+0] = mask; nctr = ctr+0; ++n; } + // end of points tests, check result for row: + // check gap and angle, if no points or big angle, it is end of inf + if( !n || abs(nctr%src_w - x) >= maxwidth+len*maxangle/57 ) break; + ctr = nctr + src_w; // new center for next row test + } + } + } +} + +void DeScratchMain::mark_scratches_plane(int comp, int mask, int value) +{ + int bpp = 3, dst_w = dst->get_w(), dst_h = dst->get_h(); + uint8_t **rows = dst->get_rows(); + for( int y=0; yget_rows(); + uint8_t **dst_rows = dst->get_rows(); + uint8_t **blur_rows = blurry->get_rows(); + int bpp = 3, margin = r+config.border+2, wm = src_w-margin; + float nrm = 1. / 1024.f, nrm2r = nrm / (2*r*bpp); + + for( int y=0; yrs; i-=bpp ) { // at right border + int rv = inp[i] + blur[rt] - blur[i]; + int v = nrm*(fade*rv + fade1*inp[rt]); + out[i] = CLIP(v,0,255); + } + left = 0; + } + } + ip += src_w; + } +} + +void DeScratchMain::pass(int comp, int thresh) +{ +// pass for current plane and current sign + get_extrems_plane(comp, thresh); + if( config.min_width > 1 ) + remove_min_extrems_plane(comp, thresh); + close_gaps(); + test_scratches(); + if( config.mark ) { + int value = config.threshold > 0 ? 0 : 255; + mark_scratches_plane(comp, SD_GOOD, value); + mark_scratches_plane(comp, SD_REJECT, 127); + } + else + remove_scratches_plane(comp); +} + +void DeScratchMain::blur(int scale) +{ + int tw = src_w, th = (src_h / scale) & ~1; + if( tmp_frame && + (tmp_frame->get_w() != tw || tmp_frame->get_h() != th) ) { + delete tmp_frame; tmp_frame = 0; + } + if( !tmp_frame ) + tmp_frame = new VFrame(tw, th, BC_YUV888); + + if( blurry && + (blurry->get_w() != src_w || blurry->get_h() != src_h) ) { + delete blurry; blurry = 0; + } + if( !blurry ) + blurry = new VFrame(src_w, src_h, BC_YUV888); + + overlay_frame->overlay(tmp_frame, src, + 0,0,src_w,src_h, 0,0,tw,th, 1.f, TRANSFER_NORMAL, LINEAR_LINEAR); + overlay_frame->overlay(blurry, tmp_frame, + 0,0,tw,th, 0,0,src_w,src_h, 1.f, TRANSFER_NORMAL, CUBIC_CUBIC); +} + +void DeScratchMain::copy(int comp) +{ + uint8_t **src_rows = src->get_rows(); + uint8_t **dst_rows = dst->get_rows(); + for( int y=0; yget_w(); + src_h = input->get_h(); + if( src_w >= 2*config.max_width+3 ) { + if( !overlay_frame ) { + int cpus = PluginClient::smp + 1; + if( cpus > 8 ) cpus = 8; + overlay_frame = new OverlayFrame(cpus); + } + if( src && (src->get_w() != src_w || src->get_h() != src_h) ) { + delete src; src = 0; + } + if( !src ) src = new VFrame(src_w, src_h, BC_YUV888); + src->transfer_from(input); + if( dst && (dst->get_w() != src_w || dst->get_h() != src_h) ) { + delete dst; dst = 0; + } + if( !dst ) dst = new VFrame(src_w, src_h, BC_YUV888); + dst->copy_from(src); + int sz = src_w * src_h; + if( sz_inf != sz ) { delete [] inf; inf = 0; } + if( !inf ) inf = new uint8_t[sz_inf=sz]; + blur(config.blur_len + 1); + plane_pass(0, config.mode_y); + plane_pass(1, config.mode_u); + plane_pass(2, config.mode_v); + output->transfer_from(dst); + } + return 0; +} + +void DeScratchMain::update_gui() +{ + if( !thread ) return; + DeScratchWindow *window = (DeScratchWindow *)thread->get_window(); + window->lock_window("DeScratchMain::update_gui"); + if( load_configuration() ) + window->update_gui(); + window->unlock_window(); +} + +NEW_WINDOW_MACRO(DeScratchMain, DeScratchWindow) + + +DeScratchWindow::DeScratchWindow(DeScratchMain *plugin) + : PluginClientWindow(plugin, 512, 256, 512, 256, 0) +{ + this->plugin = plugin; +} + +DeScratchWindow::~DeScratchWindow() +{ +} + +void DeScratchWindow::create_objects() +{ + int x = 10, y = 10; + plugin->load_configuration(); + DeScratchConfig &config = plugin->config; + + BC_Title *title; + add_tool(title = new BC_Title(x, y, _("DeScratch:"))); + y += title->get_h() + 5; + int x1 = x, x2 = get_w()/2; + add_tool(title = new BC_Title(x1=x, y, _("threshold:"))); + x1 += title->get_w()+16; + add_tool(threshold = new DeScratchISlider(this, x1, y, x2-x1-10, 0,64, &config.threshold)); + add_tool(title = new BC_Title(x1=x2, y, _("asymmetry:"))); + x1 += title->get_w()+16; + add_tool(asymmetry = new DeScratchISlider(this, x1, y, get_w()-x1-15, 0,64, &config.asymmetry)); + y += threshold->get_h() + 10; + + add_tool(title = new BC_Title(x1=x, y, _("Mode:"))); + x1 += title->get_w()+16; + add_tool(title = new BC_Title(x1, y, _("y:"))); + int w1 = title->get_w()+16; + add_tool(y_mode = new DeScratchMode(this, (x1+=w1), y, &config.mode_y)); + y_mode->create_objects(); x1 += y_mode->get_w()+16; + add_tool(title = new BC_Title(x1, y, _("u:"))); + add_tool(u_mode = new DeScratchMode(this, (x1+=w1), y, &config.mode_u)); + u_mode->create_objects(); x1 += u_mode->get_w()+16; + add_tool(title = new BC_Title(x1, y, _("v:"))); + add_tool(v_mode = new DeScratchMode(this, (x1+=w1), y, &config.mode_v)); + v_mode->create_objects(); + y += y_mode->get_h() + 10; + + add_tool(title = new BC_Title(x1=x, y, _("width:"))); + w1 = title->get_w()+16; x1 += w1; + add_tool(title = new BC_Title(x1, y, _("min:"))); + x1 += title->get_w()+16; + add_tool(min_width = new DeScratchISlider(this, x1, y, x2-x1-10, 0,16, &config.min_width)); + add_tool(title = new BC_Title(x1=x2, y, _("max:"))); + x1 += title->get_w()+16; + add_tool(max_width = new DeScratchISlider(this, x1, y, get_w()-x1-15, 0,16, &config.max_width)); + y += min_width->get_h() + 10; + + add_tool(title = new BC_Title(x1=x, y, _("len:"))); + w1 = title->get_w()+16; x1 += w1; + add_tool(title = new BC_Title(x1, y, _("min:"))); + x1 += title->get_w()+16; + add_tool(min_len = new DeScratchFSlider(this, x1, y, x2-x1-10, 0.0,100.0, &config.min_len)); + add_tool(title = new BC_Title(x1=x2, y, _("max:"))); + x1 += title->get_w()+16; + add_tool(max_len = new DeScratchFSlider(this, x1, y, get_w()-x1-15, 0.0,100.0, &config.max_len)); + y += min_len->get_h() + 10; + + add_tool(title = new BC_Title(x1=x, y, _("len:"))); + w1 = title->get_w()+16; x1 += w1; + add_tool(title = new BC_Title(x1, y, _("blur:"))); + x1 += title->get_w()+16; + add_tool(blur_len = new DeScratchISlider(this, x1, y, x2-x1-10, 0,16, &config.blur_len)); + add_tool(title = new BC_Title(x1=x2, y, _("gap:"))); + x1 += title->get_w()+16; + add_tool(gap_len = new DeScratchFSlider(this, x1, y, get_w()-x1-15, 0.0,100.0, &config.gap_len)); + y += blur_len->get_h() + 10; + + add_tool(title = new BC_Title(x1=x, y, _("max angle:"))); + w1 = title->get_w()+16; x1 += w1; + add_tool(max_angle = new DeScratchFSlider(this, x1, y, x2-x1-10, 0.0,90.0, &config.max_angle)); + add_tool(title = new BC_Title(x1=x2, y, _("fade:"))); + x1 += title->get_w()+16; + add_tool(ffade = new DeScratchFSlider(this, x1, y, get_w()-x1-15, 0.0,100.0, &config.ffade)); + y += max_angle->get_h() + 10; + + add_tool(title = new BC_Title(x1=x, y, _("border:"))); + x1 += title->get_w()+16; + add_tool(border = new DeScratchISlider(this, x1, y, x2-x1-10, 0,16, &config.border)); + add_tool(mark = new DeScratchMark(this, x1=x2, y)); + w1 = DeScratchReset::calculate_w(this, _("Reset")); + add_tool(reset = new DeScratchReset(this, get_w()-w1-15, y)); + + show_window(); +} + +void DeScratchWindow::update_gui() +{ + DeScratchConfig &config = plugin->config; + y_mode->update(config.mode_y); + u_mode->update(config.mode_u); + v_mode->update(config.mode_v); + min_width->update(config.min_width); + max_width->update(config.max_width); + min_len->update(config.min_len); + max_len->update(config.max_len); + blur_len->update(config.blur_len); + gap_len->update(config.gap_len); + max_angle->update(config.max_angle); + ffade->update(config.ffade); + mark->update(config.mark); +} + + +DeScratchModeItem::DeScratchModeItem(DeScratchMode *popup, int type, const char *text) + : BC_MenuItem(text) +{ + this->popup = popup; + this->type = type; +} + +DeScratchModeItem::~DeScratchModeItem() +{ +} + +int DeScratchModeItem::handle_event() +{ + popup->update(type); + return popup->handle_event(); +} + +DeScratchMode::DeScratchMode(DeScratchWindow *win, int x, int y, int *value) + : BC_PopupMenu(x, y, 64, "", 1) +{ + this->win = win; + this->value = value; +} + +DeScratchMode::~DeScratchMode() +{ +} + +void DeScratchMode::create_objects() +{ + add_item(new DeScratchModeItem(this, MODE_NONE, _("None"))); + add_item(new DeScratchModeItem(this, MODE_LOW, _("Low"))); + add_item(new DeScratchModeItem(this, MODE_HIGH, _("High"))); + add_item(new DeScratchModeItem(this, MODE_ALL, _("All"))); + set_value(*value); +} + +int DeScratchMode::handle_event() +{ + win->plugin->send_configure_change(); + return 1; +} + +void DeScratchMode::update(int v) +{ + set_value(*value = v); +} + +void DeScratchMode::set_value(int v) +{ + int i = total_items(); + while( --i >= 0 && ((DeScratchModeItem*)get_item(i))->type != v ); + if( i >= 0 ) set_text(get_item(i)->get_text()); +} + +DeScratchISlider::DeScratchISlider(DeScratchWindow *win, + int x, int y, int w, int min, int max, int *output) + : BC_ISlider(x, y, 0, w, w, min, max, *output) +{ + this->win = win; + this->output = output; +} + +DeScratchISlider::~DeScratchISlider() +{ +} + +int DeScratchISlider::handle_event() +{ + *output = get_value(); + win->plugin->send_configure_change(); + return 1; +} + +DeScratchFSlider::DeScratchFSlider(DeScratchWindow *win, + int x, int y, int w, float min, float max, float *output) + : BC_FSlider(x, y, 0, w, w, min, max, *output) +{ + this->win = win; + this->output = output; +} + +DeScratchFSlider::~DeScratchFSlider() +{ +} + +int DeScratchFSlider::handle_event() +{ + *output = get_value(); + win->plugin->send_configure_change(); + return 1; +} + +DeScratchMark::DeScratchMark(DeScratchWindow *win, int x, int y) + : BC_CheckBox(x, y, &win->plugin->config.mark, _("Mark")) +{ + this->win = win; +}; + +DeScratchMark::~DeScratchMark() +{ +} + +int DeScratchMark::handle_event() +{ + int ret = BC_CheckBox::handle_event(); + win->plugin->send_configure_change(); + return ret; +} + +DeScratchReset::DeScratchReset(DeScratchWindow *win, int x, int y) + : BC_GenericButton(x, y, _("Reset")) +{ + this->win = win; +} + +int DeScratchReset::handle_event() +{ + win->plugin->config.reset(); + win->update_gui(); + win->plugin->send_configure_change(); + return 1; +} + diff --git a/cinelerra-5.1/plugins/descratch/descratch.h b/cinelerra-5.1/plugins/descratch/descratch.h new file mode 100644 index 00000000..b6c726dd --- /dev/null +++ b/cinelerra-5.1/plugins/descratch/descratch.h @@ -0,0 +1,187 @@ +#ifndef __DESCRATCH_H__ +#define __DESCRATCH_H__ + +#include "bcbutton.h" +#include "bchash.h" +#include "bcmenuitem.h" +#include "bcpopupmenu.h" +#include "bcslider.h" +#include "bctitle.h" +#include "bctoggle.h" +#include "mutex.h" +#include "overlayframe.h" +#include "pluginvclient.h" + +// so that write_pgm can create grey images of inf +#define SD_NULL 0 +#define SD_EXTREM 0x80 +#define SD_TESTED 0x60 +#define SD_GOOD 0x40 +#define SD_REJECT 0x10 + +#define MODE_NONE 0 +#define MODE_LOW 1 +#define MODE_HIGH 2 +#define MODE_ALL 3 + +class DeScratchConfig; +class DeScratchMain; +class DeScratchWindow; +class DeScratchModeItem; +class DeScratchMode; +class DeScratchISlider; +class DeScratchFSlider; +class DeScratchMark; +class DeScratchReset; + + +class DeScratchConfig +{ +public: + DeScratchConfig(); + ~DeScratchConfig(); + void reset(); + int equivalent(DeScratchConfig &that); + void copy_from(DeScratchConfig &that); + void interpolate(DeScratchConfig &prev, DeScratchConfig &next, + int64_t prev_frame, int64_t next_frame, int64_t current_frame); + + int threshold; + int asymmetry; + int min_width; + int max_width; + float min_len; + float max_len; + float max_angle; + int blur_len; + float gap_len; + int mode_y; + int mode_u; + int mode_v; + int mark; + float ffade; + int border; +}; + +class DeScratchMain : public PluginVClient +{ +public: + DeScratchMain(PluginServer *server); + ~DeScratchMain(); + + PLUGIN_CLASS_MEMBERS(DeScratchConfig) + uint8_t *inf; int sz_inf; + int src_w, src_h; + VFrame *src, *dst; + VFrame *tmp_frame, *blurry; + OverlayFrame *overlay_frame; + int is_realtime(); + void update_gui(); + void save_data(KeyFrame *keyframe); + void read_data(KeyFrame *keyframe); + + void get_extrems_plane(int comp, int thresh); + void remove_min_extrems_plane(int comp, int thresh); + void close_gaps(); + void test_scratches(); + void mark_scratches_plane(int comp, int mask, int value); + void remove_scratches_plane(int comp); + void pass(int comp, int thresh); + void blur(int scale); + void copy(int comp); + void plane_pass(int comp, int mode); + int process_realtime(VFrame *input, VFrame *output); +}; + + +class DeScratchWindow : public PluginClientWindow +{ +public: + DeScratchWindow(DeScratchMain *plugin); + ~DeScratchWindow(); + void update_gui(); + void create_objects(); + + DeScratchMain *plugin; + DeScratchMode *y_mode, *u_mode, *v_mode; + DeScratchISlider *threshold, *asymmetry; + DeScratchISlider *min_width, *max_width; + DeScratchFSlider *min_len, *max_len; + DeScratchISlider *blur_len; + DeScratchFSlider *gap_len; + DeScratchFSlider *max_angle; + DeScratchISlider *border; + DeScratchMark *mark; + DeScratchFSlider *ffade; + DeScratchReset *reset; +}; + +class DeScratchModeItem : public BC_MenuItem +{ +public: + DeScratchModeItem(DeScratchMode *popup, int type, const char *text); + ~DeScratchModeItem(); + int handle_event(); + + DeScratchMode *popup; + int type; +}; + +class DeScratchMode : public BC_PopupMenu +{ +public: + DeScratchMode(DeScratchWindow *win, int x, int y, int *value); + ~DeScratchMode(); + void create_objects(); + int handle_event(); + void update(int v); + void set_value(int v); + + DeScratchWindow *win; + int *value; +}; + +class DeScratchISlider : public BC_ISlider +{ +public: + DeScratchISlider(DeScratchWindow *win, + int x, int y, int w, int min, int max, int *output); + ~DeScratchISlider(); + int handle_event(); + + DeScratchWindow *win; + int *output; +}; + +class DeScratchFSlider : public BC_FSlider +{ +public: + DeScratchFSlider(DeScratchWindow *win, + int x, int y, int w, float min, float max, float *output); + ~DeScratchFSlider(); + int handle_event(); + + DeScratchWindow *win; + float *output; +}; + +class DeScratchMark : public BC_CheckBox +{ +public: + DeScratchMark(DeScratchWindow *win, int x, int y); + ~DeScratchMark(); + int handle_event(); + + DeScratchWindow *win; +}; + +class DeScratchReset : public BC_GenericButton +{ +public: + DeScratchReset(DeScratchWindow *win, int x, int y); + int handle_event(); + + DeScratchWindow *win; +}; + +#endif -- 2.26.2