descratch again reworked + icons, add agingtv plugin params, add alias chkbox in...
authorGood Guy <[email protected]>
Sat, 24 Mar 2018 21:09:14 +0000 (15:09 -0600)
committerGood Guy <[email protected]>
Sat, 24 Mar 2018 21:09:14 +0000 (15:09 -0600)
15 files changed:
cinelerra-5.1/cinelerra/mwindow.C
cinelerra-5.1/cinelerra/pluginclient.C
cinelerra-5.1/guicast/vicon.C
cinelerra-5.1/picon/cinfinity/descratch.png [new file with mode: 0644]
cinelerra-5.1/picon/cinfinity2/descratch.png [new file with mode: 0644]
cinelerra-5.1/plugins/aging/aging.C
cinelerra-5.1/plugins/aging/aging.h
cinelerra-5.1/plugins/aging/agingwindow.C
cinelerra-5.1/plugins/aging/agingwindow.h
cinelerra-5.1/plugins/descratch/descratch.C
cinelerra-5.1/plugins/descratch/descratch.h
cinelerra-5.1/plugins/titler/titler.C
cinelerra-5.1/plugins/titler/titler.h
cinelerra-5.1/plugins/titler/titlerwindow.C
cinelerra-5.1/plugins/titler/titlerwindow.h

index 38e37d2f6e7fe7dc3c64d7f587b5f0c3e0cf7576..ff4de5071a26300fa2277b87fd5bb6256c4f3661 100644 (file)
@@ -746,7 +746,7 @@ void MWindow::add_plugins(ArrayList<PluginServer*> &plugins)
 void MWindow::init_plugin_tips(ArrayList<PluginServer*> &plugins, const char *lang)
 {
        const char *cfg_path = File::get_cindat_path();
-       char msg_path[BCTEXTLEN];  int txt = 0;
+       char msg_path[BCTEXTLEN];
        FILE *fp = 0;
        if( BC_Resources::language[0] ) {
                snprintf(msg_path, sizeof(msg_path), "%s/info/plugins.%s",
@@ -754,7 +754,6 @@ void MWindow::init_plugin_tips(ArrayList<PluginServer*> &plugins, const char *la
                fp = fopen(msg_path, "r");
        }
        if( !fp ) {
-               txt = 1;
                snprintf(msg_path, sizeof(msg_path), "%s/info/plugins.txt",
                        cfg_path);
                fp = fopen(msg_path, "r");
@@ -775,9 +774,8 @@ void MWindow::init_plugin_tips(ArrayList<PluginServer*> &plugins, const char *la
                if( done ) {
                        if( tp > text && *--tp == '\n' ) *tp = 0;
                        if( title[0] ) {
-                               tp = !txt ? title : _(title);
                                int idx = plugins.size();
-                               while( --idx>=0 && strcmp(plugins[idx]->title, tp) );
+                               while( --idx>=0 && strcmp(plugins[idx]->title, title) );
                                if( idx >= 0 ) {
                                        delete [] plugins[idx]->tip;
                                        plugins[idx]->tip = cstrdup(text);
index aaec69d86e107e92da749a70a46a63b3a7b6d26e..417dd917e2c4f0e9bb8e7f76b74e28323871e701 100644 (file)
@@ -149,14 +149,19 @@ PluginClientWindow::PluginClientWindow(PluginClient *client,
  : BC_Window(client->gui_string,
        client->window_x /* - w / 2 */,
        client->window_y /* - h / 2 */,
-       w, h, min_w, min_h, allow_resize, 0, 1)
+       (int)(w*get_resources()->font_scale+0.5), (int)(h*get_resources()->font_scale+0.5),
+       (int)(min_w*get_resources()->font_scale+0.5), (int)(min_h*get_resources()->font_scale+0.5),
+       allow_resize, 0, 1)
 {
        this->client = client;
 }
 
 PluginClientWindow::PluginClientWindow(const char *title,
        int x, int y, int w, int h, int min_w, int min_h, int allow_resize)
- : BC_Window(title, x, y, w, h, min_w, min_h, allow_resize, 0, 1)
+ : BC_Window(title, x, y,
+        (int)(w*get_resources()->font_scale+0.5), (int)(h*get_resources()->font_scale+0.5),
+        (int)(min_w*get_resources()->font_scale+0.5), (int)(min_h*get_resources()->font_scale+0.5),
+       allow_resize, 0, 1)
 {
        this->client = 0;
 }
index 031e9530c2b9c0bb5c22481efed7811e41b9bbe9..2bfedd9277b9a1465091361adafa7e1c757689a0 100644 (file)
@@ -175,9 +175,15 @@ void ViewPopup::draw_vframe(VFrame *frame)
 
 ViewPopup *VIconThread::new_view_window(VFrame *frame)
 {
-       int wx = viewing->get_vx() - view_w, rx = 0;
-       int wy = viewing->get_vy() - view_h, ry = 0;
-       wdw->get_root_coordinates(wx, wy, &rx, &ry);
+       BC_WindowBase *parent = wdw->get_parent();
+       XineramaScreenInfo *info = parent->get_xinerama_info(-1);
+       int cx = info ? info->x_org + info->width/2 : parent->get_root_w(0)/2;
+       int cy = info ? info->y_org + info->height/2 : parent->get_root_h(0)/2;
+       int vx = viewing->get_vx(), rx = 0;
+       int vy = viewing->get_vy(), ry = 0;
+       wdw->get_root_coordinates(vx, vy, &rx, &ry);
+       rx += (rx >= cx ? -view_w : viewing->vw);
+       ry += (ry >= cy ? -view_h : viewing->vh);
        ViewPopup *vwin = new ViewPopup(this, frame, rx, ry, view_w, view_h);
        wdw->set_active_subwindow(vwin);
        return vwin;
diff --git a/cinelerra-5.1/picon/cinfinity/descratch.png b/cinelerra-5.1/picon/cinfinity/descratch.png
new file mode 100644 (file)
index 0000000..cd2edb6
Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity/descratch.png differ
diff --git a/cinelerra-5.1/picon/cinfinity2/descratch.png b/cinelerra-5.1/picon/cinfinity2/descratch.png
new file mode 100644 (file)
index 0000000..926c63c
Binary files /dev/null and b/cinelerra-5.1/picon/cinfinity2/descratch.png differ
index 765a8fcd2e60261ff013b83650ab1365eb7c9964..d16f538453b3e1aab085c4989353c081dc1daf1a 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
-
-
-
-
-
 REGISTER_PLUGIN(AgingMain)
 
+int AgingMain::dx[] = { 1, 1, 0, -1, -1, -1,  0, 1 };
+int AgingMain::dy[] = { 0, -1, -1, -1, 0, 1, 1, 1 };
 
+AgingMain::AgingMain(PluginServer *server)
+ : PluginVClient(server)
+{
+       aging_server = 0;
+       pits_count = 0;
+       dust_count = 0;
+}
 
+AgingMain::~AgingMain()
+{
 
+       delete aging_server;
+}
 
+const char* AgingMain::plugin_title() { return N_("AgingTV"); }
+int AgingMain::is_realtime() { return 1; }
 
-int AgingConfig::dx[] = { 1, 1, 0, -1, -1, -1,  0, 1};
-int AgingConfig::dy[] = { 0, -1, -1, -1, 0, 1, 1, 1};
-
-AgingConfig::AgingConfig()
+void AgingConfig::reset()
 {
+       area_scale = 10;
+       aging_mode = 0;
        dust_interval = 0;
        pits_interval = 0;
-       aging_mode = 0;
-       area_scale = 10;
        scratch_lines = 7;
        colorage = 1;
        scratch = 1;
@@ -60,48 +67,96 @@ AgingConfig::AgingConfig()
        dust = 1;
 }
 
-AgingMain::AgingMain(PluginServer *server)
- : PluginVClient(server)
+AgingConfig::AgingConfig()
 {
-
-       aging_server = 0;
+       reset();
 }
 
-AgingMain::~AgingMain()
+AgingConfig::~AgingConfig()
 {
-
-       if(aging_server) delete aging_server;
 }
 
-const char* AgingMain::plugin_title() { return N_("AgingTV"); }
-int AgingMain::is_realtime() { return 1; }
-
-NEW_WINDOW_MACRO(AgingMain, AgingWindow)
-
-int AgingMain::load_defaults()
+int AgingConfig::equivalent(AgingConfig &that)
 {
-       return 0;
+       return area_scale == that.area_scale &&
+               aging_mode == that.aging_mode &&
+               dust_interval == that.dust_interval &&
+               pits_interval == that.pits_interval &&
+               scratch_lines == that.scratch_lines &&
+               colorage == that.colorage &&
+               scratch == that.scratch &&
+               pits == that.pits &&
+               dust == that.dust;
 }
 
-int AgingMain::save_defaults()
+void AgingConfig::copy_from(AgingConfig &that)
 {
-       return 0;
+       area_scale = that.area_scale;
+       aging_mode = that.aging_mode;
+       dust_interval = that.dust_interval;
+       pits_interval = that.pits_interval;
+       scratch_lines = that.scratch_lines;
+       colorage = that.colorage;
+       scratch = that.scratch;
+       pits = that.pits;
+       dust = that.dust;
 }
 
-int AgingMain::load_configuration()
+void AgingConfig::interpolate(AgingConfig &prev, AgingConfig &next,
+               int64_t prev_frame, int64_t next_frame, int64_t current_frame)
 {
-       return 0;
+       copy_from(prev);
 }
 
+LOAD_CONFIGURATION_MACRO(AgingMain, AgingConfig)
 
 void AgingMain::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("AGING");
+       output.tag.set_property("AREA_SCALE", config.area_scale);
+       output.tag.set_property("AGING_MODE", config.aging_mode);
+       output.tag.set_property("DUST_INTERVAL", config.dust_interval);
+       output.tag.set_property("PITS_INTERVAL", config.pits_interval);
+       output.tag.set_property("SCRATCH_LINES", config.scratch_lines);
+       output.tag.set_property("COLORAGE", config.colorage);
+       output.tag.set_property("SCRATCH", config.scratch);
+       output.tag.set_property("PITS", config.pits);
+       output.tag.set_property("DUST", config.dust);
+       output.append_tag();
+       output.tag.set_title("/AGING");
+       output.append_tag();
+       output.append_newline();
+       output.terminate_string();
 }
 
 void AgingMain::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("AGING") ) {
+                       config.area_scale    = input.tag.get_property("AREA_SCALE", config.area_scale);
+                       config.aging_mode    = input.tag.get_property("AGING_MODE", config.aging_mode);
+                       config.dust_interval = input.tag.get_property("DUST_INTERVAL", config.dust_interval);
+                       config.pits_interval = input.tag.get_property("PITS_INTERVAL", config.pits_interval);
+                       config.scratch_lines = input.tag.get_property("SCRATCH_LINES", config.scratch_lines);
+                       config.colorage      = input.tag.get_property("COLORAGE", config.colorage);
+                       config.scratch       = input.tag.get_property("SCRATCH", config.scratch);
+                       config.pits          = input.tag.get_property("PITS", config.pits);
+                       config.dust          = input.tag.get_property("DUST", config.dust);
+               }
+       }
 }
 
+NEW_WINDOW_MACRO(AgingMain, AgingWindow)
+
 
 int AgingMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
 {
@@ -110,10 +165,10 @@ int AgingMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
 //printf("AgingMain::process_realtime 1\n");
        this->input_ptr = input_ptr;
        this->output_ptr = output_ptr;
-
-       if(!aging_server) aging_server = new AgingServer(this,
-               PluginClient::smp + 1,
-               PluginClient::smp + 1);
+       int cpus = PluginClient::smp + 1;
+       if( cpus > 16 ) cpus = 16;
+       if( !aging_server )
+               aging_server = new AgingServer(this, cpus, cpus);
        aging_server->process_packages();
 //printf("AgingMain::process_realtime 2\n");
 
@@ -121,7 +176,6 @@ int AgingMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
 }
 
 
-
 AgingServer::AgingServer(AgingMain *plugin, int total_clients, int total_packages)
  : LoadServer(1, 1 /* total_clients, total_packages */)
 {
@@ -134,20 +188,14 @@ LoadClient* AgingServer::new_client()
        return new AgingClient(this);
 }
 
-
-
-
 LoadPackage* AgingServer::new_package()
 {
        return new AgingPackage;
 }
 
-
-
 void AgingServer::init_packages()
 {
-       for(int i = 0; i < get_total_packages(); i++)
-       {
+       for( int i = 0; i < get_total_packages(); i++ ) {
                AgingPackage *package = (AgingPackage*)get_package(i);
                package->row1 = plugin->input_ptr->get_h() * i / get_total_packages();
                package->row2 = plugin->input_ptr->get_h() * (i + 1) / get_total_packages();
@@ -155,60 +203,37 @@ void AgingServer::init_packages()
 }
 
 
-
-
-
-
-
-
 AgingClient::AgingClient(AgingServer *server)
  : LoadClient(server)
 {
        this->plugin = server->plugin;
 }
 
-
-
-
-
-
-
-
-
 #define COLORAGE(type, components) \
 { \
        int a, b; \
        int i, j, k; \
  \
-       for(i = 0; i < h; i++) \
-       { \
-               for(j = 0; j < w; j++) \
-               { \
-                       for(k = 0; k < 3; k++) \
-                       { \
-                               if(sizeof(type) == 4) \
-                               { \
+       for( i = 0; i < h; i++ ) { \
+               for( j = 0; j < w; j++ ) { \
+                       for( k = 0; k < 3; k++ ) { \
+                               if( sizeof(type) == 4 ) { \
                                        a = (int)(((type**)input_rows)[i][j * components + k] * 0xffff); \
                                        CLAMP(a, 0, 0xffff); \
                                } \
                                else \
                                        a = (int)((type**)input_rows)[i][j * components + k]; \
- \
-                               if(sizeof(type) == 4) \
-                               { \
+                               if( sizeof(type) == 4 ) { \
                                        b = (a & 0xffff) >> 2; \
                                        ((type**)output_rows)[i][j * components + k] = \
                                                (type)(a - b + 0x1800 + (EffectTV::fastrand() & 0x1000)) / 0xffff; \
                                } \
-                               else \
-                               if(sizeof(type) == 2) \
-                               { \
+                               else if( sizeof(type) == 2 ) { \
                                        b = (a & 0xffff) >> 2; \
                                        ((type**)output_rows)[i][j * components + k] = \
                                                (type)(a - b + 0x1800 + (EffectTV::fastrand() & 0x1000)); \
                                } \
-                               else \
-                               { \
+                               else { \
                                        b = (a & 0xff) >> 2; \
                                        ((type**)output_rows)[i][j * components + k] =  \
                                                (type)(a - b + 0x18 + ((EffectTV::fastrand() >> 8) & 0x10)); \
@@ -218,49 +243,40 @@ AgingClient::AgingClient(AgingServer *server)
        } \
 }
 
-void AgingClient::coloraging(unsigned char **output_rows,
-       unsigned char **input_rows,
-       int color_model,
-       int w,
-       int h)
+void AgingClient::coloraging(unsigned char **output_rows, unsigned char **input_rows,
+               int color_model, int w, int h)
 {
-       switch(color_model)
-       {
-               case BC_RGB888:
-               case BC_YUV888:
-                       COLORAGE(uint8_t, 3);
-                       break;
-
-               case BC_RGB_FLOAT:
-                       COLORAGE(float, 3);
-                       break;
-
-               case BC_RGBA_FLOAT:
-                       COLORAGE(float, 4);
-                       break;
-
-               case BC_RGBA8888:
-               case BC_YUVA8888:
-                       COLORAGE(uint8_t, 4);
-                       break;
-
-               case BC_RGB161616:
-               case BC_YUV161616:
-                       COLORAGE(uint16_t, 3);
-                       break;
-
-               case BC_RGBA16161616:
-               case BC_YUVA16161616:
-                       COLORAGE(uint16_t, 4);
-                       break;
+       switch( color_model ) {
+       case BC_RGB888:
+       case BC_YUV888:
+               COLORAGE(uint8_t, 3);
+               break;
+
+       case BC_RGB_FLOAT:
+               COLORAGE(float, 3);
+               break;
+
+       case BC_RGBA_FLOAT:
+               COLORAGE(float, 4);
+               break;
+
+       case BC_RGBA8888:
+       case BC_YUVA8888:
+               COLORAGE(uint8_t, 4);
+               break;
+
+       case BC_RGB161616:
+       case BC_YUV161616:
+               COLORAGE(uint16_t, 3);
+               break;
+
+       case BC_RGBA16161616:
+       case BC_YUVA16161616:
+               COLORAGE(uint16_t, 4);
+               break;
        }
 }
 
-
-
-
-
-
 #define SCRATCHES(type, components, chroma) \
 { \
        int i, j, y, y1, y2; \
@@ -268,47 +284,33 @@ void AgingClient::coloraging(unsigned char **output_rows,
        int a, b; \
        int w_256 = w * 256; \
  \
-       for(i = 0; i < plugin->config.scratch_lines; i++) \
-       { \
-               if(plugin->config.scratches[i].life)  \
-               { \
-                       plugin->config.scratches[i].x = plugin->config.scratches[i].x + plugin->config.scratches[i].dx; \
-                       if(plugin->config.scratches[i].x < 0 || plugin->config.scratches[i].x > w_256)  \
-                       { \
-                               plugin->config.scratches[i].life = 0; \
+       for( i = 0; i < plugin->config.scratch_lines; i++ ) { \
+               if( plugin->scratches[i].life )  { \
+                       plugin->scratches[i].x = plugin->scratches[i].x + plugin->scratches[i].dx; \
+                       if( plugin->scratches[i].x < 0 || plugin->scratches[i].x > w_256 ) { \
+                               plugin->scratches[i].life = 0; \
                                break; \
                        } \
-\
-                       p = (type*)output_rows[0] + \
-                               (plugin->config.scratches[i].x >> 8) * \
-                               components; \
-\
-                       if(plugin->config.scratches[i].init)  \
-                       { \
-                               y1 = plugin->config.scratches[i].init; \
-                               plugin->config.scratches[i].init = 0; \
-                       }  \
-                       else  \
-                       { \
+                       p = (type*)output_rows[0] + (plugin->scratches[i].x >> 8) * components; \
+                       if( plugin->scratches[i].init ) { \
+                               y1 = plugin->scratches[i].init; \
+                               plugin->scratches[i].init = 0; \
+                       } \
+                       else { \
                                y1 = 0; \
                        } \
 \
-                       plugin->config.scratches[i].life--; \
-                       if(plugin->config.scratches[i].life)  \
-                       { \
+                       plugin->scratches[i].life--; \
+                       if( plugin->scratches[i].life ) { \
                                y2 = h; \
                        }  \
-                       else  \
-                       { \
+                       else { \
                                y2 = EffectTV::fastrand() % h; \
                        } \
  \
-                       for(y = y1; y < y2; y++)  \
-                       { \
-                               for(j = 0; j < (chroma ? 1 : 3); j++) \
-                               { \
-                                       if(sizeof(type) == 4) \
-                                       { \
+                       for( y = y1; y < y2; y++ ) { \
+                               for( j = 0; j < (chroma ? 1 : 3); j++ ) { \
+                                       if( sizeof(type) == 4 ) { \
                                                int temp = (int)(p[j] * 0xffff); \
                                                CLAMP(temp, 0, 0xffff); \
                                                a = temp & 0xfeff; \
@@ -316,17 +318,14 @@ void AgingClient::coloraging(unsigned char **output_rows,
                                                b = a & 0x10000; \
                                                p[j] = (type)(a | (b - (b >> 8))) / 0xffff; \
                                        } \
-                                       else \
-                                       if(sizeof(type) == 2) \
-                                       { \
+                                       else if( sizeof(type) == 2 ) { \
                                                int temp = (int)p[j]; \
                                                a = temp & 0xfeff; \
                                                a += 0x2000; \
                                                b = a & 0x10000; \
                                                p[j] = (type)(a | (b - (b >> 8))); \
                                        } \
-                                       else \
-                                       { \
+                                       else { \
                                                int temp = (int)p[j]; \
                                                a = temp & 0xfe; \
                                                a += 0x20; \
@@ -334,144 +333,113 @@ void AgingClient::coloraging(unsigned char **output_rows,
                                                p[j] = (type)(a | (b - (b >> 8))); \
                                        } \
                                } \
- \
-                               if(chroma) \
-                               { \
+                               if( chroma ) { \
                                        p[1] = chroma; \
                                        p[2] = chroma; \
                                } \
                                p += w * components; \
                        } \
                }  \
-               else  \
-               { \
-                       if((EffectTV::fastrand() & 0xf0000000) == 0)  \
-                       { \
-                               plugin->config.scratches[i].life = 2 + (EffectTV::fastrand() >> 27); \
-                               plugin->config.scratches[i].x = EffectTV::fastrand() % (w_256); \
-                               plugin->config.scratches[i].dx = ((int)EffectTV::fastrand()) >> 23; \
-                               plugin->config.scratches[i].init = (EffectTV::fastrand() % (h - 1)) + 1; \
+               else  { \
+                       if( (EffectTV::fastrand() & 0xf0000000) == 0 ) { \
+                               plugin->scratches[i].life = 2 + (EffectTV::fastrand() >> 27); \
+                               plugin->scratches[i].x = EffectTV::fastrand() % (w_256); \
+                               plugin->scratches[i].dx = ((int)EffectTV::fastrand()) >> 23; \
+                               plugin->scratches[i].init = (EffectTV::fastrand() % (h - 1)) + 1; \
                        } \
                } \
        } \
 }
 
 
-
 void AgingClient::scratching(unsigned char **output_rows,
-       int color_model,
-       int w,
-       int h)
+               int color_model, int w, int h)
 {
-       switch(color_model)
-       {
-               case BC_RGB888:
-                       SCRATCHES(uint8_t, 3, 0);
-                       break;
-
-               case BC_RGB_FLOAT:
-                       SCRATCHES(float, 3, 0);
-                       break;
-
-               case BC_YUV888:
-                       SCRATCHES(uint8_t, 3, 0x80);
-                       break;
-
-               case BC_RGBA_FLOAT:
-                       SCRATCHES(float, 4, 0);
-                       break;
-
-               case BC_RGBA8888:
-                       SCRATCHES(uint8_t, 4, 0);
-                       break;
-
-               case BC_YUVA8888:
-                       SCRATCHES(uint8_t, 4, 0x80);
-                       break;
-
-               case BC_RGB161616:
-                       SCRATCHES(uint16_t, 3, 0);
-                       break;
-
-               case BC_YUV161616:
-                       SCRATCHES(uint16_t, 3, 0x8000);
-                       break;
-
-               case BC_RGBA16161616:
-                       SCRATCHES(uint16_t, 4, 0);
-                       break;
-
-               case BC_YUVA16161616:
-                       SCRATCHES(uint16_t, 4, 0x8000);
-                       break;
+       switch( color_model ) {
+       case BC_RGB888:
+               SCRATCHES(uint8_t, 3, 0);
+               break;
+
+       case BC_RGB_FLOAT:
+               SCRATCHES(float, 3, 0);
+               break;
+
+       case BC_YUV888:
+               SCRATCHES(uint8_t, 3, 0x80);
+               break;
+
+       case BC_RGBA_FLOAT:
+               SCRATCHES(float, 4, 0);
+               break;
+
+       case BC_RGBA8888:
+               SCRATCHES(uint8_t, 4, 0);
+               break;
+
+       case BC_YUVA8888:
+               SCRATCHES(uint8_t, 4, 0x80);
+               break;
+
+       case BC_RGB161616:
+               SCRATCHES(uint16_t, 3, 0);
+               break;
+
+       case BC_YUV161616:
+               SCRATCHES(uint16_t, 3, 0x8000);
+               break;
+
+       case BC_RGBA16161616:
+               SCRATCHES(uint16_t, 4, 0);
+               break;
+
+       case BC_YUVA16161616:
+               SCRATCHES(uint16_t, 4, 0x8000);
+               break;
        }
 }
 
 
-
 #define PITS(type, components, luma, chroma) \
 { \
        int i, j, k; \
        int pnum, size, pnumscale; \
        int x, y; \
- \
        pnumscale = plugin->config.area_scale * 2; \
- \
-       if(plugin->config.pits_interval)  \
-       { \
-               pnum = pnumscale + (EffectTV::fastrand() % pnumscale); \
-               plugin->config.pits_interval--; \
+       pnum = EffectTV::fastrand() % (plugin->config.pits_interval+1); \
+       if( plugin->pits_count ) { \
+               pnum += pnumscale; \
+               --plugin->pits_count; \
        }  \
-       else \
-       { \
-               pnum = EffectTV::fastrand() % pnumscale; \
-               if((EffectTV::fastrand() & 0xf8000000) == 0)  \
-               { \
-                       plugin->config.pits_interval = (EffectTV::fastrand() >> 28) + 20; \
+       else { \
+               if( (EffectTV::fastrand() & 0xf8000000) == 0 ) { \
+                       plugin->pits_count = (EffectTV::fastrand() >> 28) + 20; \
                } \
        } \
- \
-       for(i = 0; i < pnum; i++)  \
-       { \
+       for( i = 0; i < pnum; i++ ) { \
                x = EffectTV::fastrand() % (w - 1); \
                y = EffectTV::fastrand() % (h - 1); \
- \
                size = EffectTV::fastrand() >> 28; \
- \
-               for(j = 0; j < size; j++)  \
-               { \
+               for( j = 0; j < size; j++ ) { \
                        x = x + EffectTV::fastrand() % 3 - 1; \
                        y = y + EffectTV::fastrand() % 3 - 1; \
- \
                        CLAMP(x, 0, w - 1); \
                        CLAMP(y, 0, h - 1); \
-                       for(k = 0; k < (chroma ? 1 : 3); k++) \
-                       { \
+                       for( k = 0; k < (chroma ? 1 : 3); k++ ) { \
                                ((type**)output_rows)[y][x * components + k] = luma; \
                        } \
- \
-            if(chroma) \
-                       { \
+                       if( chroma ) { \
                                ((type**)output_rows)[y][x * components + 1] = chroma; \
                                ((type**)output_rows)[y][x * components + 2] = chroma; \
                        } \
- \
                } \
        } \
 }
 
 
-
-
-
-
 void AgingClient::pits(unsigned char **output_rows,
-       int color_model,
-       int w,
-       int h)
+               int color_model, int w, int h)
 {
-       switch(color_model)
-       {
+       switch( color_model ) {
                case BC_RGB888:
                        PITS(uint8_t, 3, 0xc0, 0);
                        break;
@@ -515,147 +483,116 @@ void AgingClient::pits(unsigned char **output_rows,
        int dnum; \
        int d, len; \
        int x, y; \
- \
-       if(plugin->config.dust_interval == 0)  \
-       { \
-               if((EffectTV::fastrand() & 0xf0000000) == 0)  \
-               { \
-                       plugin->config.dust_interval = EffectTV::fastrand() >> 29; \
+       if( plugin->dust_count == 0 ) { \
+               if( (EffectTV::fastrand() & 0xf0000000) == 0 ) { \
+                       plugin->dust_count = EffectTV::fastrand() >> 29; \
                } \
                return; \
        } \
- \
-       dnum = plugin->config.area_scale * 4 + (EffectTV::fastrand() >> 27); \
- \
-       for(i = 0; i < dnum; i++)  \
-       { \
+       dnum = plugin->config.area_scale * 4 + EffectTV::fastrand() % (plugin->config.dust_interval+1); \
+       for( i = 0; i < dnum; i++ ) { \
                x = EffectTV::fastrand() % w; \
                y = EffectTV::fastrand() % h; \
                d = EffectTV::fastrand() >> 29; \
                len = EffectTV::fastrand() % plugin->config.area_scale + 5; \
- \
-               for(j = 0; j < len; j++)  \
-               { \
+               for( j = 0; j < len; j++ ) { \
                        CLAMP(x, 0, w - 1); \
                        CLAMP(y, 0, h - 1); \
-                       for(k = 0; k < (chroma ? 1 : 3); k++) \
-                       { \
+                       for( k = 0; k < (chroma ? 1 : 3); k++ ) { \
                                ((type**)output_rows)[y][x * components + k] = luma; \
                        } \
- \
-                       if(chroma) \
-                       { \
+                       if( chroma ) { \
                                ((type**)output_rows)[y][x * components + 1] = chroma; \
                                ((type**)output_rows)[y][x * components + 2] = chroma; \
                        } \
- \
-                       y += AgingConfig::dy[d]; \
-                       x += AgingConfig::dx[d]; \
- \
-                       if(x < 0 || x >= w) break; \
-                       if(y < 0 || y >= h) break; \
- \
- \
+                       y += AgingMain::dy[d]; \
+                       x += AgingMain::dx[d]; \
+                       if( x < 0 || x >= w ) break; \
+                       if( y < 0 || y >= h ) break; \
                        d = (d + EffectTV::fastrand() % 3 - 1) & 7; \
                } \
        } \
-       plugin->config.dust_interval--; \
+       --plugin->dust_count; \
 }
 
 
-
-
 void AgingClient::dusts(unsigned char **output_rows,
-       int color_model,
-       int w,
-       int h)
+               int color_model, int w, int h)
 {
-       switch(color_model)
-       {
-               case BC_RGB888:
-                       DUSTS(uint8_t, 3, 0x10, 0);
-                       break;
-
-               case BC_RGB_FLOAT:
-                       DUSTS(float, 3, (float)0x10 / 0xff, 0);
-                       break;
-
-               case BC_YUV888:
-                       DUSTS(uint8_t, 3, 0x10, 0x80);
-                       break;
-
-               case BC_RGBA_FLOAT:
-                       DUSTS(float, 4, (float)0x10 / 0xff, 0);
-                       break;
-
-               case BC_RGBA8888:
-                       DUSTS(uint8_t, 4, 0x10, 0);
-                       break;
-
-               case BC_YUVA8888:
-                       DUSTS(uint8_t, 4, 0x10, 0x80);
-                       break;
-
-               case BC_RGB161616:
-                       DUSTS(uint16_t, 3, 0x1000, 0);
-                       break;
-
-               case BC_YUV161616:
-                       DUSTS(uint16_t, 3, 0x1000, 0x8000);
-                       break;
-
-               case BC_RGBA16161616:
-                       DUSTS(uint16_t, 4, 0x1000, 0);
-                       break;
-
-               case BC_YUVA16161616:
-                       DUSTS(uint16_t, 4, 0x1000, 0x8000);
-                       break;
+       switch( color_model ) {
+       case BC_RGB888:
+               DUSTS(uint8_t, 3, 0x10, 0);
+               break;
+
+       case BC_RGB_FLOAT:
+               DUSTS(float, 3, (float)0x10 / 0xff, 0);
+               break;
+
+       case BC_YUV888:
+               DUSTS(uint8_t, 3, 0x10, 0x80);
+               break;
+
+       case BC_RGBA_FLOAT:
+               DUSTS(float, 4, (float)0x10 / 0xff, 0);
+               break;
+
+       case BC_RGBA8888:
+               DUSTS(uint8_t, 4, 0x10, 0);
+               break;
+
+       case BC_YUVA8888:
+               DUSTS(uint8_t, 4, 0x10, 0x80);
+               break;
+
+       case BC_RGB161616:
+               DUSTS(uint16_t, 3, 0x1000, 0);
+               break;
+
+       case BC_YUV161616:
+               DUSTS(uint16_t, 3, 0x1000, 0x8000);
+               break;
+
+       case BC_RGBA16161616:
+               DUSTS(uint16_t, 4, 0x1000, 0);
+               break;
+
+       case BC_YUVA16161616:
+               DUSTS(uint16_t, 4, 0x1000, 0x8000);
+               break;
        }
 }
 
 
-
 void AgingClient::process_package(LoadPackage *package)
 {
-//printf("AgingClient::process_package 1\n");
        AgingPackage *local_package = (AgingPackage*)package;
        unsigned char **input_rows = plugin->input_ptr->get_rows() + local_package->row1;
        unsigned char **output_rows = plugin->output_ptr->get_rows() + local_package->row1;
 
-//printf("AgingClient::process_package 1\n");
-       if(plugin->config.colorage)
+       if( plugin->config.colorage )
                coloraging(output_rows,
                        input_rows,
                        plugin->input_ptr->get_color_model(),
                        plugin->input_ptr->get_w(),
                        local_package->row2 - local_package->row1);
-//printf("AgingClient::process_package 2\n");
-       if(plugin->config.scratch)
+       if( plugin->config.scratch )
                scratching(output_rows,
                        plugin->input_ptr->get_color_model(),
                        plugin->input_ptr->get_w(),
                        local_package->row2 - local_package->row1);
-//printf("AgingClient::process_package 3\n");
-       if(plugin->config.pits)
+       if( plugin->config.pits )
                pits(output_rows,
                        plugin->input_ptr->get_color_model(),
                        plugin->input_ptr->get_w(),
                        local_package->row2 - local_package->row1);
-//printf("AgingClient::process_package 4 %d\n", plugin->config.dust);
-       if(plugin->config.dust)
+       if( plugin->config.dust )
                dusts(output_rows,
                        plugin->input_ptr->get_color_model(),
                        plugin->input_ptr->get_w(),
                        local_package->row2 - local_package->row1);
-//printf("AgingClient::process_package 5\n");
 }
 
-
-
 AgingPackage::AgingPackage()
 {
 }
 
-
-
index 8be9fd85435e8f5911f6f0a481afd01fcb4de1f4..534beb805c1cd8fc957cd9fb2bc6177809d3f6d3 100644 (file)
@@ -34,35 +34,23 @@ class AgingEngine;
 
 #define SCRATCH_MAX 20
 
-
-typedef struct _scratch
-{
-       int life;
-       int x;
-       int dx;
-       int init;
-} scratch_t;
-
 class AgingConfig
 {
 public:
        AgingConfig();
+       ~AgingConfig();
+
+       void reset();
+       int equivalent(AgingConfig &that);
+       void copy_from(AgingConfig &that);
+       void interpolate(AgingConfig &prev, AgingConfig &next,
+               int64_t prev_frame, int64_t next_frame, int64_t current_frame);
 
        int area_scale;
        int aging_mode;
-       scratch_t scratches[SCRATCH_MAX];
-
-       static int dx[8];
-       static int dy[8];
        int dust_interval;
-
-
        int pits_interval;
-
        int scratch_lines;
-       int pit_count;
-       int dust_count;
-
        int colorage;
        int scratch;
        int pits;
@@ -93,28 +81,26 @@ class AgingClient : public LoadClient
 public:
        AgingClient(AgingServer *server);
 
-       void coloraging(unsigned char **output_ptr,
-               unsigned char **input_ptr,
-               int color_model,
-               int w,
-               int h);
+       void coloraging(unsigned char **output_ptr, unsigned char **input_ptr,
+                       int color_model, int w, int h);
        void scratching(unsigned char **output_ptr,
-               int color_model,
-               int w,
-               int h);
+                       int color_model, int w, int h);
        void pits(unsigned char **output_ptr,
-               int color_model,
-               int w,
-               int h);
+                       int color_model, int w, int h);
        void dusts(unsigned char **output_ptr,
-               int color_model,
-               int w,
-               int h);
+                       int color_model, int w, int h);
        void process_package(LoadPackage *package);
 
        AgingMain *plugin;
 };
 
+typedef struct _scratch {
+       int life;
+       int x;
+       int dx;
+       int init;
+} scratch_t;
+
 
 class AgingMain : public PluginVClient
 {
@@ -129,14 +115,15 @@ public:
        void save_data(KeyFrame *keyframe);
        void read_data(KeyFrame *keyframe);
 
-       int load_defaults();
-       int save_defaults();
-
        AgingServer *aging_server;
        AgingClient *aging_client;
 
        AgingEngine **engine;
        VFrame *input_ptr, *output_ptr;
+
+       int pits_count, dust_count;
+       scratch_t scratches[SCRATCH_MAX];
+       static int dx[8], dy[8];
 };
 
 
index 213d998e690e6cf8e9285a857d69cb82aadf23e5..9c702d7ed42610fabfd24d7b14d490adcbf72e36 100644 (file)
 #include "agingwindow.h"
 #include "language.h"
 
-
-
-
-
-
-
-
-AgingWindow::AgingWindow(AgingMain *client)
- : PluginClientWindow(client,
-       300,
-       170,
-       300,
-       170,
-       0)
+AgingWindow::AgingWindow(AgingMain *plugin)
+ : PluginClientWindow(plugin, 300, 180, 300, 180, 0)
 {
-       this->client = client;
+       this->plugin = plugin;
 }
 
 AgingWindow::~AgingWindow()
@@ -48,171 +36,65 @@ AgingWindow::~AgingWindow()
 void AgingWindow::create_objects()
 {
        int x = 10, y = 10;
-       add_subwindow(new BC_Title(x, y,
-               "Film aging from EffectTV\n"
-               "Copyright (C) 2001 FUKUCHI Kentarou")
-       );
-// 
-//     y += 50;
-//     add_subwindow(color = new AgingColor(x, y, client));
-// 
-//     y += 25;
-//     add_subwindow(scratches = new AgingScratches(x, y, client));
-//     add_subwindow(scratch_count = new AgingScratchCount(x + 100, y + 10, client));
-// 
-//     y += 25;
-//     add_subwindow(pits = new AgingPits(x, y, client));
-//     add_subwindow(pit_count = new AgingPitCount(x + 100, y + 10, client));
-// 
-//     y += 25;
-//     add_subwindow(dust = new AgingDust(x, y, client));
-//     add_subwindow(dust_count = new AgingDustCount(x + 100, y + 10, client));
-
-       show_window();
-       flush();
-}
-
-
-
-
-
-
-
-
-AgingColor::AgingColor(int x, int y, AgingMain *plugin)
- : BC_CheckBox(x, y, plugin->config.colorage, _("Grain"))
-{
-       this->plugin = plugin;
-}
-
-int AgingColor::handle_event()
-{
-       return 1;
-}
-
-
-
-
-
-AgingScratches::AgingScratches(int x, int y, AgingMain *plugin)
- : BC_CheckBox(x, y, plugin->config.scratch, _("Scratch"))
-{
-       this->plugin = plugin;
-}
-
-int AgingScratches::handle_event()
-{
-       return 1;
-}
-
-
-
-
-
-
-
+       BC_Title *title;
+       add_subwindow(title = new BC_Title(x, y, _("Aging:")));
+       y += title->get_h() + 15;
 
+       add_subwindow(color = new AgingCheckBox(this, x, y,
+               &plugin->config.colorage, _("Grain")));
+       y += color->get_h() + 5;
 
-AgingScratchCount::AgingScratchCount(int x, int y, AgingMain *plugin)
- : BC_ISlider(x,
-                       y,
-                       0,
-                       180,
-                       180,
-                       0,
-                       SCRATCH_MAX,
-                       plugin->config.scratch_lines)
-{
-       this->plugin = plugin;
-}
-
-int AgingScratchCount::handle_event()
-{
-       return 1;
-}
+       add_subwindow(scratches = new AgingCheckBox(this, x, y,
+               &plugin->config.scratch, _("Scratch")));
+       add_subwindow(scratch_count = new AgingISlider(this, x+100, y, 180,
+               0,SCRATCH_MAX, &plugin->config.scratch_lines));
+       y += scratches->get_h() + 5;
 
+       add_subwindow(pits = new AgingCheckBox(this, x, y,
+               &plugin->config.pits, _("Pits")));
+       add_subwindow(pit_count = new AgingISlider(this, x+100, y, 180,
+               0,100, &plugin->config.pits_interval));
+       y += pits->get_h() + 5;
 
+       add_subwindow(dust = new AgingCheckBox(this, x, y,
+               &plugin->config.dust, _("Dust")));
+       add_subwindow(dust_count = new AgingISlider(this, x+100, y, 180,
+               0,100, &plugin->config.dust_interval));
 
-
-
-
-AgingPits::AgingPits(int x, int y, AgingMain *plugin)
- : BC_CheckBox(x, y, plugin->config.pits, _("Pits"))
-{
-       this->plugin = plugin;
+       show_window(1);
 }
 
-int AgingPits::handle_event()
-{
-       return 1;
-}
-
-
-
 
-
-
-AgingPitCount::AgingPitCount(int x, int y, AgingMain *plugin)
- : BC_ISlider(x,
-                       y,
-                       0,
-                       180,
-                       180,
-                       0,
-                       100,
-                       plugin->config.pit_count)
+AgingISlider::AgingISlider(AgingWindow *win,
+               int x, int y, int w, int min, int max, int *output)
+ : BC_ISlider(x, y, 0, w, w, min, max, *output)
 {
-       this->plugin = plugin;
+       this->win = win;
+       this->output = output;
 }
 
-int AgingPitCount::handle_event()
+AgingISlider::~AgingISlider()
 {
-       return 1;
 }
 
-
-
-
-
-
-
-
-
-AgingDust::AgingDust(int x, int y, AgingMain *plugin)
- : BC_CheckBox(x, y, plugin->config.dust, _("Dust"))
-{
-       this->plugin = plugin;
-}
-
-int AgingDust::handle_event()
+int AgingISlider::handle_event()
 {
-       return 1;
+       int ret = BC_ISlider::handle_event();
+       win->plugin->send_configure_change();
+       return ret;
 }
 
-
-
-
-
-AgingDustCount::AgingDustCount(int x, int y, AgingMain *plugin)
- : BC_ISlider(x,
-                       y,
-                       0,
-                       180,
-                       180,
-                       0,
-                       100,
-                       plugin->config.dust_count)
+AgingCheckBox::AgingCheckBox(AgingWindow *win, int x, int y,
+               int *output, const char *text)
+ : BC_CheckBox(x, y, output, text)
 {
-       this->plugin = plugin;
+       this->win = win;
 }
 
-int AgingDustCount::handle_event()
+int AgingCheckBox::handle_event()
 {
-       return 1;
+       int ret = BC_CheckBox::handle_event();
+       win->plugin->send_configure_change();
+       return ret;
 }
 
-
-
-
-
-
index 9d593b4ed217152ba1e1f68dd8304dd78356828a..5f0bce88654bc7e4ce0e6db2ec1827d24d36bf11 100644 (file)
@@ -31,108 +31,46 @@ class AgingWindow;
 #include "mutex.h"
 #include "aging.h"
 
-
-class AgingColor;
-class AgingScratches;
-class AgingScratchCount;
-class AgingPits;
-class AgingPitCount;
-class AgingDust;
-class AgingDustCount;
+class AgingCheckBox;
+class AgingISlider;
 
 class AgingWindow : public PluginClientWindow
 {
 public:
-       AgingWindow(AgingMain *client);
+       AgingWindow(AgingMain *plugin);
        ~AgingWindow();
 
        void create_objects();
-
-       AgingMain *client;
-
-
-       AgingColor *color;
-       AgingScratches *scratches;
-       AgingScratchCount *scratch_count;
-       AgingPits *pits;
-       AgingPitCount *pit_count;
-       AgingDust *dust;
-       AgingDustCount *dust_count;
-};
-
-
-
-
-
-class AgingColor : public BC_CheckBox
-{
-public:
-       AgingColor(int x, int y, AgingMain *plugin);
-       int handle_event();
        AgingMain *plugin;
-};
-
 
-class AgingScratches : public BC_CheckBox
-{
-public:
-       AgingScratches(int x, int y, AgingMain *plugin);
-       int handle_event();
-       AgingMain *plugin;
+       AgingCheckBox *color;
+       AgingCheckBox *scratches;
+       AgingISlider *scratch_count;
+       AgingCheckBox *pits;
+       AgingISlider *pit_count;
+       AgingCheckBox *dust;
+       AgingISlider *dust_count;
 };
 
-
-class AgingScratchCount : public BC_ISlider
+class AgingISlider : public BC_ISlider
 {
 public:
-       AgingScratchCount(int x, int y, AgingMain *plugin);
+       AgingISlider(AgingWindow *win,
+               int x, int y, int w, int min, int max, int *output);
+       ~AgingISlider();
        int handle_event();
-       AgingMain *plugin;
-};
 
-class AgingPits : public BC_CheckBox
-{
-public:
-       AgingPits(int x, int y, AgingMain *plugin);
-       int handle_event();
-       AgingMain *plugin;
+       AgingWindow *win;
+       int *output;
 };
 
-class AgingPitCount : public BC_ISlider
+class AgingCheckBox : public BC_CheckBox
 {
 public:
-       AgingPitCount(int x, int y, AgingMain *plugin);
+       AgingCheckBox(AgingWindow *win, int x, int y, int *output, const char *text);
        int handle_event();
-       AgingMain *plugin;
-};
-
-
-
-
-
 
-
-
-class AgingDust : public BC_CheckBox
-{
-public:
-       AgingDust(int x, int y, AgingMain *plugin);
-       int handle_event();
-       AgingMain *plugin;
+       AgingWindow *win;
 };
 
-class AgingDustCount : public BC_ISlider
-{
-public:
-       AgingDustCount(int x, int y, AgingMain *plugin);
-       int handle_event();
-       AgingMain *plugin;
-};
-
-
-
-
-
-
-
 #endif
index 8375510f0c242b4f446bca16f7cf2427a8bda91f..b94fc9dab4962052a6815ff6e49557a1f7dec9ba 100644 (file)
@@ -8,6 +8,7 @@ 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
+Adapted strategy to mark, test, draw during port.
 */
 
 
@@ -16,6 +17,8 @@ Reworked for cin5 by GG. 03/2018, from the laws of Fizick's
 #include "language.h"
 #include "descratch.h"
 
+#include <math.h>
+
 REGISTER_PLUGIN(DeScratchMain)
 
 DeScratchMain::DeScratchMain(PluginServer *server)
@@ -23,8 +26,7 @@ DeScratchMain::DeScratchMain(PluginServer *server)
 {
        inf = 0;  sz_inf = 0;
        src = 0;  dst = 0;
-       tmp_frame = 0;
-       blurry = 0;
+       tmpy = 0; blury = 0;
        overlay_frame = 0;
 }
 
@@ -33,8 +35,8 @@ DeScratchMain::~DeScratchMain()
        delete [] inf;
        delete src;
        delete dst;
-       delete blurry;
-       delete tmp_frame;
+       delete blury;
+       delete tmpy;
        delete overlay_frame;
 }
 
@@ -43,21 +45,22 @@ int DeScratchMain::is_realtime() { return 1; }
 
 void DeScratchConfig::reset()
 {
-       threshold = 24;
-       asymmetry = 16;
+       threshold = 12;
+       asymmetry = 25;
        min_width = 1;
-       max_width = 3;
-       min_len = 1;
+       max_width = 2;
+       min_len = 10;
        max_len = 100;
-       max_angle = 45;
-       blur_len = 4;
-       gap_len = 10;
+       max_angle = 5;
+       blur_len = 2;
+       gap_len = 0;
        mode_y = MODE_ALL;
        mode_u = MODE_NONE;
        mode_v = MODE_NONE;
        mark = 0;
        ffade = 100;
        border = 2;
+       edge_only = 0;
 }
 
 DeScratchConfig::DeScratchConfig()
@@ -85,7 +88,8 @@ int DeScratchConfig::equivalent(DeScratchConfig &that)
                mode_v == that.mode_v &&
                mark == that.mark &&
                ffade == that.ffade &&
-               border == that.border;
+               border == that.border &&
+               edge_only == that.edge_only;
 }
 void DeScratchConfig::copy_from(DeScratchConfig &that)
 {
@@ -104,6 +108,7 @@ void DeScratchConfig::copy_from(DeScratchConfig &that)
        mark = that.mark;
        ffade = that.ffade;
        border = that.border;
+       edge_only = that.edge_only;
 }
 
 void DeScratchConfig::interpolate(DeScratchConfig &prev, DeScratchConfig &next,
@@ -136,6 +141,7 @@ void DeScratchMain::save_data(KeyFrame *keyframe)
        output.tag.set_property("MARK", config.mark);
        output.tag.set_property("FFADE", config.ffade);
        output.tag.set_property("BORDER", config.border);
+       output.tag.set_property("EDGE_ONLY", config.edge_only);
        output.append_tag();
        output.tag.set_title("/DESCRATCH");
        output.append_tag();
@@ -153,7 +159,7 @@ void DeScratchMain::read_data(KeyFrame *keyframe)
        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.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);
@@ -167,100 +173,64 @@ void DeScratchMain::read_data(KeyFrame *keyframe)
                        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);
+                       config.edge_only = input.tag.get_property("EDGE_ONLY", config.edge_only);
                }
        }
 }
 
-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<src_h; ++y ) {
-                       uint8_t *ip = inf + y*src_w;
-                       int x = 0;
-                       for( ; x<d1; ++x ) *ip++ = SD_NULL;
-                       uint8_t *dp = rows[y] + x*bpp + comp;
-                       for( ; x<wd; ++x,dp+=bpp ) {
-                               uint8_t *lp = dp-dsz, *rp = dp+dsz;
-                               *ip++ = (lp[0]-*dp) > 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( ; x<src_w; ++x ) *ip++ = SD_NULL;
-               }
-       }
-       else {                  // white (high value) scratches
-               for( int y=0; y<src_h; ++y ) {
-                       uint8_t *ip = inf + y*src_w;
-                       int x = 0;
-                       for( ; x<d1; ++x ) *ip++ = SD_NULL;
-                       uint8_t *dp = rows[y] + x*bpp + comp;
-                       for( ; x<wd; ++x,dp+=bpp ) {
-                               uint8_t *lp = dp-dsz, *rp = dp+dsz;
-                               *ip++ = (lp[0]-*dp) < 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( ; x<src_w; ++x ) *ip++ = SD_NULL;
-               }
-       }
-}
-
-//
-void DeScratchMain::remove_min_extrems_plane(int comp, int thresh)
+void DeScratchMain::set_extrems_plane(int width, int comp, int thresh)
 {
-       uint8_t **rows = blurry->get_rows();
-       int d = config.min_width, d1 = d+1, wd = src_w - d1;
-       int bpp = 3, dsz = d * bpp;
-       int asym = config.asymmetry;
+       uint8_t **rows = blury->get_rows();
+       int r = width, r1 = r+1, wd = src_w - r1;
+       int bpp = 3, dsz = r * bpp;
+       int asym = config.asymmetry * 256 / 100;
        if( thresh > 0 ) {      // black (low value) scratches
                for( int y=0; y<src_h; ++y ) {
-                       uint8_t *ip = inf + y*src_w;
-                       uint8_t *dp = rows[y] + d1*bpp + comp;
-                       for( int x=d1; x<wd; ++x,++ip,dp+=bpp ) {
-                               if( *ip != SD_EXTREM ) continue;
+                       uint8_t *ip = inf + y*src_w + r1;
+                       uint8_t *dp = rows[y] + r1*bpp + comp;
+                       for( int x=r1; x<wd; ++x,++ip,dp+=bpp ) {
+                               if( *ip != SD_NULL ) continue;
                                uint8_t *lp = dp-dsz, *rp = dp+dsz;
                                if( (lp[0]-*dp) > 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
+                                   (abs(lp[-bpp]-rp[+bpp]) <= asym) &&
+                                   ((lp[0]-lp[+bpp]) + (rp[0]-rp[-bpp]) >
+                                    (lp[-bpp]-lp[0]) + (rp[bpp]-rp[0])) ) {
+                                       *ip = SD_EXTREM;
+                                       for( int i=1; i<r; ++i ) ip[i] = ip[-i] = SD_EXTREM;
+                               }
                        }
                }
        }
        else {                  // white (high value) scratches
                for( int y=0; y<src_h; ++y ) {
-                       uint8_t *ip = inf + y*src_w;
-                       uint8_t *dp = rows[y] + d1*bpp + comp;
-                       for( int x=d1; x<wd; ++x,++ip,dp+=bpp ) {
-                               if( *ip != SD_EXTREM ) continue;
+                       uint8_t *ip = inf + y*src_w + r1;
+                       uint8_t *dp = rows[y] + r1*bpp + comp;
+                       for( int x=r1; x<wd; ++x,++ip,dp+=bpp ) {
+                               if( *ip != SD_NULL ) continue;
                                uint8_t *lp = dp-dsz, *rp = dp+dsz;
                                if( (lp[0]-*dp) < 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
+                                   (abs(lp[-bpp]-rp[+bpp]) <= asym) &&
+                                   ((lp[0]-lp[+bpp]) + (rp[0]-rp[-bpp]) <
+                                    (lp[-bpp]-lp[0]) + (rp[bpp]-rp[0])) ) {
+                                       *ip = SD_EXTREM;
+                                       for( int i=1; i<r; ++i ) ip[i] = ip[-i] = SD_EXTREM;
+                               }
                        }
                }
        }
 }
 
+//
 void DeScratchMain::close_gaps()
 {
        int len = config.gap_len * src_h / 100;
-       for( int y=len; y<src_h; ++y ) {
+       for( int y=0; y<src_h; ++y ) {
                uint8_t *ip = inf + y*src_w;
                for( int x=0; x<src_w; ++x,++ip ) {
-                       if( *ip != SD_EXTREM ) continue;
-                       uint8_t *bp = ip;                       // expand to previous lines in range
-                       for( int i=len; --i>0; ) *(bp-=src_w) = SD_EXTREM;
+                       if( !(*ip & SD_EXTREM) ) continue;
+                       uint8_t *bp = ip, b = *bp;              // expand to previous lines in range
+                       int i = len < y ? len : y;
+                       while( --i>=0 ) *(bp-=src_w) = b;
                }
        }
 }
@@ -270,153 +240,140 @@ 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;
+       int maxwidth = config.max_width;
+       float sin_mxa = sin(config.max_angle * M_PI/180.);
 
        for( int y=0; y<src_h; ++y ) {
                for( int x=2; x<w2; ++x ) {
-                       int ofs = y*src_w + x;                  // offset of first candidate
-                       if( inf[ofs] != SD_EXTREM ) continue;
-                       int ctr = ofs+1, nctr = ctr;            // centered to inf for maxwidth=3
+                       int ofs = y*src_w + x;                  // first candidate
+                       if( !(inf[ofs] & SD_EXTREM) ) continue;
+                       int ctr = ofs, nctr = ctr;
                        int hy = src_h - y, len;
-                       for( len=0; len<hy; ++len ) {           // cycle along inf
+                       for( len=0; len<hy; ++len ) {           // check vertical aspect
                                uint8_t *ip = inf + ctr;
                                int n = 0;                      // number good points in row
-                               if( maxwidth >= 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
+                               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; }
+                               if( !n ) 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
+                       int v = (!config.edge_only || y == 0 || y+len>=src_h) &&
+                               abs(nctr%src_w - x) < maxwidth + len*sin_mxa &&
+                               len >= min_len && len <= max_len ? SD_GOOD : SD_REJECT;
+                       ctr = ofs; nctr = ctr;                  // pass2
                        for( len=0; len<hy; ++len ) {           // cycle along inf
                                uint8_t *ip = inf + ctr;
                                int n = 0;                      // number good points in row
-                               if( maxwidth >= 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
+                               if( ip[-1] & SD_TESTED ) { ip[-1] = v; nctr = ctr-1; ++n; }
+                               if( ip[+1] & SD_TESTED ) { ip[+1] = v; nctr = ctr+1; ++n; }
+                               if( ip[+0] & SD_TESTED ) { ip[+0] = v; nctr = ctr+0; ++n; }
+                               if( !n ) break;
+                               ctr = nctr + src_w;             // new center for next row test
                        }
                }
        }
 }
 
-void DeScratchMain::mark_scratches_plane(int comp, int mask, int value)
+void DeScratchMain::mark_scratches_plane()
 {
        int bpp = 3, dst_w = dst->get_w(), dst_h = dst->get_h();
        uint8_t **rows = dst->get_rows();
        for( int y=0; y<dst_h; ++y ) {
-               uint8_t *dp = rows[y] + comp;
                uint8_t *ip = inf + y*src_w;
-               for( int x=0; x<dst_w; ++x,++ip,dp+=bpp ) {
-                       if( *ip == mask ) *dp = value;
+               for( int x=0; x<dst_w; ++x,++ip ) {
+                       if( *ip == SD_NULL ) continue;
+                       static uint8_t grn_yuv[3] = { 0xad, 0x28, 0x19, };
+                       static uint8_t ylw_yuv[3] = { 0xdb, 0x0f, 0x89, };
+                       static uint8_t red_yuv[3] = { 0x40, 0x66, 0xef, };
+                       for( int comp=0; comp<3; ++comp ) {
+                               uint8_t *dp = rows[y] + comp + x*bpp;
+                               if( *ip & SD_GOOD )
+                                       *dp = config.threshold > 0 ? grn_yuv[comp] : red_yuv[comp];
+                               else if( *ip & SD_REJECT )
+                                       *dp = ylw_yuv[comp];
+                       }
                }
        }
 }
 
 void DeScratchMain::remove_scratches_plane(int comp)
 {
-       int r = config.max_width;
-       int fade = (config.ffade * 1024) / 100; // norm 2^10
-       int fade1 = 1024 - fade;
+       int bpp = 3, w1 = src_w-1;
+       int border = config.border;
        uint8_t *ip = inf;
-       uint8_t **src_rows = src->get_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);
+       uint8_t **blur_rows = blury->get_rows();
+       float a = config.ffade / 100, b = 1 - a;
 
        for( int y=0; y<src_h; ++y ) {
-               int left = 0;
-               uint8_t *inp = src_rows[y] + comp;
+               int left = -1;
                uint8_t *out = dst_rows[y] + comp;
                uint8_t *blur = blur_rows[y] + comp;
-               for( int x=margin; x<wm; ++x ) {
+               for( int x=1; x<w1; ++x ) {
                        uint8_t *dp = ip + x;
-                       if( (dp[+0]&SD_GOOD) && !(dp[-1]&SD_GOOD) ) left = x;
-                       if( left!=0 && (dp[+0]&SD_GOOD) && !(dp[+1]&SD_GOOD) ) { // the inf, left/right
-                               int right = x;
-                               int ctr = (left + right) / 2;                   // the inf center
-                               int ls = ctr - r, rs = ctr + r;
-                               int lt = ls - config.border - 1, rt = rs + config.border + 1;
-                               lt *= bpp;  ls *= bpp;  rs *= bpp;  rt *= bpp;  // component index
-                               for( int i=ls; i<=rs; i+=bpp ) {                // across the inf
-                                       int lv = inp[i] + blur[lt] - blur[i];
-                                       int rv = inp[i] + blur[rt] - blur[i];
-                                       lv = fade*lv + fade1*inp[lt];
-                                       rv = fade*rv + fade1*inp[rt];
-                                       int v = nrm2r*(lv*(rs-i) + rv*(i-ls));
-                                       out[i] = CLIP(v,0,255);
-                               }
-                               for( int i=lt; i<ls; i+=bpp ) {                  // at left border
-                                       int lv = inp[i] + blur[lt] - blur[i];
-                                       int v = nrm*(fade*lv + fade1*inp[lt]);
-                                       out[i] = CLIP(v,0,255);
-                               }
-                               for( int i=rt; i>rs; 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;
+                       if( !(dp[-1]&SD_GOOD) && (dp[0]&SD_GOOD) ) left = x;
+                       if( left < 0 || !(dp[0]&SD_GOOD) || (dp[1]&SD_GOOD) ) continue;
+                       int right = x;
+                       int ctr = (left + right) / 2;                   // scratch center
+                       int r = (right - left + border) / 2 + 1;
+                       left = 0;
+                       int ls = ctr - r, rs = ctr + r;                 // scratch edges
+                       int lt = ls - border, rt = rs + border;         // border edges
+                       if( ls < 0 ) ls = 0;
+                       if( rs > w1 ) rs = w1;
+                       if( lt < 0 ) lt = 0;
+                       if( rt > w1 ) rt = w1;
+                       ls *= bpp;  rs *= bpp;
+                       lt *= bpp;  rt *= bpp;
+                       if( rs > ls ) {
+                               float s = 1. / (rs - ls);
+                               for( int i=ls; (i+=bpp)<rs; ) {         // across the scratch
+                                       int lv = a * blur[ls] + b * out[i];
+                                       int rv = a * blur[rs] + b * out[i];
+                                       int v = s * (lv*(rs-i) + rv*(i-ls));
+                                       out[i] = CLIP(v, 0, 255);
+                               }
+                       }
+                       if( !border ) continue;
+                       if( ls > lt ) {
+                               float s = 1. / (ls - lt);
+                               for( int i=lt; (i+=bpp)<=ls; ) {        // at left border
+                                       int lv = a * out[lt] + b * out[i];
+                                       int rv = a * blur[i] + b * out[i];
+                                       int v = s * (lv*(ls-i) + rv*(i-lt));
+                                       out[i] = CLIP(v, 0, 255);
+                               }
+                       }
+                       if( rt > rs ) {
+                               float s = 1. / (rt - rs);
+                               for( int i=rt; (i-=bpp)>=rs; ) {        // at right border
+                                       int lv = a * blur[i] + b * out[i];
+                                       int rv = a * out[rt] + b * out[i];
+                                       int v = s * (rv*(i-rs) + lv*(rt-i));
+                                       out[i] = CLIP(v, 0, 255);
+                               }
                        }
                }
                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;
+       int th = (src_h / scale) & ~1;
+       if( tmpy&& (tmpy->get_w() != src_w || tmpy->get_h() != th) ) {
+               delete tmpy;  tmpy= 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( !tmpy ) tmpy = new VFrame(src_w, th, BC_YUV888);
+       if( blury && (blury->get_w() != src_w || blury->get_h() != src_h) ) {
+               delete blury;  blury= 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);
+       if( !blury ) blury = new VFrame(src_w, src_h, BC_YUV888);
+       overlay_frame->overlay(tmpy, src,
+               0,0,src_w,src_h, 0,0,src_w,th, 1.f, TRANSFER_NORMAL, LINEAR_LINEAR);
+       overlay_frame->overlay(blury, tmpy,
+               0,0,src_w,th, 0,0,src_w,src_h, 1.f, TRANSFER_NORMAL, CUBIC_CUBIC);
 }
 
 void DeScratchMain::copy(int comp)
@@ -429,6 +386,15 @@ void DeScratchMain::copy(int comp)
        }
 }
 
+void DeScratchMain::pass(int comp, int thresh)
+{
+// pass for current plane and current sign
+       int w0 = config.min_width, w1 = config.max_width;
+       if( w1 < w0 ) w1 = w0;
+       for( int iw=w0; iw<=w1; ++iw )
+               set_extrems_plane(iw, comp, thresh);
+}
+
 void DeScratchMain::plane_pass(int comp, int mode)
 {
        int threshold = config.threshold;
@@ -445,6 +411,12 @@ void DeScratchMain::plane_pass(int comp, int mode)
        }
 }
 
+void DeScratchMain::plane_proc(int comp, int mode)
+{
+       if( mode == MODE_NONE ) return;
+       remove_scratches_plane(comp);
+}
+
 int DeScratchMain::process_realtime(VFrame *input, VFrame *output)
 {
        load_configuration();
@@ -470,9 +442,19 @@ int DeScratchMain::process_realtime(VFrame *input, VFrame *output)
                if( sz_inf != sz ) {  delete [] inf;  inf = 0; }
                if( !inf ) inf = new uint8_t[sz_inf=sz];
                blur(config.blur_len + 1);
+               memset(inf, SD_NULL, sz_inf);
                plane_pass(0, config.mode_y);
                plane_pass(1, config.mode_u);
                plane_pass(2, config.mode_v);
+               close_gaps();
+               test_scratches();
+               if( !config.mark ) {
+                       plane_proc(0, config.mode_y);
+                       plane_proc(1, config.mode_u);
+                       plane_proc(2, config.mode_v);
+               }
+               else
+                       mark_scratches_plane();
                output->transfer_from(dst);
        }
        return 0;
@@ -516,7 +498,7 @@ void DeScratchWindow::create_objects()
        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));
+       add_tool(asymmetry = new DeScratchFSlider(this, x1, y, get_w()-x1-15, 0,100., &config.asymmetry));
        y += threshold->get_h() + 10;
 
        add_tool(title = new BC_Title(x1=x, y, _("Mode:")));
@@ -537,10 +519,10 @@ void DeScratchWindow::create_objects()
        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(min_width = new DeScratchISlider(this, x1, y, x2-x1-10, 1,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));
+       add_tool(max_width = new DeScratchISlider(this, x1, y, get_w()-x1-15, 1,16, &config.max_width));
        y += min_width->get_h() + 10;
 
        add_tool(title = new BC_Title(x1=x, y, _("len:")));
@@ -557,7 +539,7 @@ void DeScratchWindow::create_objects()
        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(blur_len = new DeScratchISlider(this, x1, y, x2-x1-10, 0,8, &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));
@@ -565,7 +547,7 @@ void DeScratchWindow::create_objects()
 
        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(max_angle = new DeScratchFSlider(this, x1, y, x2-x1-10, 0.0,15.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));
@@ -575,8 +557,12 @@ void DeScratchWindow::create_objects()
        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));
+       x1 += mark->get_w() + 10;
+       add_tool(edge_only = new DeScratchEdgeOnly(this, x1, y));
+
        w1 = DeScratchReset::calculate_w(this, _("Reset"));
-       add_tool(reset = new DeScratchReset(this, get_w()-w1-15, y));
+       int h1 = DeScratchReset::calculate_h();
+       add_tool(reset = new DeScratchReset(this, get_w()-w1-15, get_h()-h1-15));
 
        show_window();
 }
@@ -584,18 +570,22 @@ void DeScratchWindow::create_objects()
 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);
+       threshold->update(config.threshold);
+       asymmetry->update(config.asymmetry);
        min_width->update(config.min_width);
        max_width->update(config.max_width);
        min_len->update(config.min_len);
        max_len->update(config.max_len);
+       max_angle->update(config.max_angle);
        blur_len->update(config.blur_len);
        gap_len->update(config.gap_len);
-       max_angle->update(config.max_angle);
-       ffade->update(config.ffade);
+       y_mode->update(config.mode_y);
+       u_mode->update(config.mode_u);
+       v_mode->update(config.mode_v);
        mark->update(config.mark);
+       ffade->update(config.ffade);
+       border->update(config.border);
+       edge_only->update(config.edge_only);
 }
 
 
@@ -709,6 +699,23 @@ int DeScratchMark::handle_event()
        return ret;
 }
 
+DeScratchEdgeOnly::DeScratchEdgeOnly(DeScratchWindow *win, int x, int y)
+ : BC_CheckBox(x, y, &win->plugin->config.edge_only, _("Edge"))
+{
+       this->win = win;
+};
+
+DeScratchEdgeOnly::~DeScratchEdgeOnly()
+{
+}
+
+int DeScratchEdgeOnly::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"))
 {
index b6c726ddd85826243358afd2973ef2a04171a31f..841899f54b97c1a02d024d1d9802e06c4778f796 100644 (file)
@@ -15,8 +15,8 @@
 // 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_TESTED 0x40
+#define SD_GOOD   0x20
 #define SD_REJECT 0x10
 
 #define MODE_NONE 0
@@ -32,6 +32,7 @@ class DeScratchMode;
 class DeScratchISlider;
 class DeScratchFSlider;
 class DeScratchMark;
+class DeScratchEdgeOnly;
 class DeScratchReset;
 
 
@@ -47,7 +48,7 @@ public:
                int64_t prev_frame, int64_t next_frame, int64_t current_frame);
 
        int threshold;
-       int asymmetry;
+       float asymmetry;
        int min_width;
        int max_width;
        float min_len;
@@ -61,6 +62,7 @@ public:
        int mark;
        float ffade;
        int border;
+       int edge_only;
 };
 
 class DeScratchMain : public PluginVClient
@@ -73,23 +75,23 @@ public:
        uint8_t *inf;  int sz_inf;
        int src_w, src_h;
        VFrame *src, *dst;
-       VFrame *tmp_frame, *blurry;
+       VFrame *tmpy, *blury;
        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 set_extrems_plane(int width, int comp, int thresh);
        void close_gaps();
        void test_scratches();
-       void mark_scratches_plane(int comp, int mask, int value);
+       void mark_scratches_plane();
        void remove_scratches_plane(int comp);
-       void pass(int comp, int thresh);
        void blur(int scale);
        void copy(int comp);
+       void pass(int comp, int thresh);
        void plane_pass(int comp, int mode);
+       void plane_proc(int comp, int mode);
        int process_realtime(VFrame *input, VFrame *output);
 };
 
@@ -104,7 +106,8 @@ public:
        
        DeScratchMain *plugin;
        DeScratchMode *y_mode, *u_mode, *v_mode;
-       DeScratchISlider *threshold, *asymmetry;
+       DeScratchISlider *threshold;
+       DeScratchFSlider *asymmetry;
        DeScratchISlider *min_width, *max_width;
        DeScratchFSlider *min_len, *max_len;
        DeScratchISlider *blur_len;
@@ -112,6 +115,7 @@ public:
        DeScratchFSlider *max_angle;
        DeScratchISlider *border;
        DeScratchMark *mark;
+       DeScratchEdgeOnly *edge_only;
        DeScratchFSlider *ffade;
        DeScratchReset *reset;
 };
@@ -175,6 +179,16 @@ public:
        DeScratchWindow *win;
 };
 
+class DeScratchEdgeOnly : public BC_CheckBox
+{
+public:
+       DeScratchEdgeOnly(DeScratchWindow *win, int x, int y);
+       ~DeScratchEdgeOnly();
+       int handle_event();
+
+       DeScratchWindow *win;
+};
+
 class DeScratchReset : public BC_GenericButton
 {
 public:
index 117e279e77fd91b394ff71eaf1095fd78b338423..9056bc19a9ec8fa333392729ba3f389d883b0ef2 100644 (file)
@@ -82,7 +82,7 @@ TitleConfig::TitleConfig()
 {
        strcpy(font, "fixed");
        strcpy(encoding, DEFAULT_ENCODING);
-       style = 0;
+       style = FONT_ALIAS;
        size = 24;
        color = BLACK;
        alpha = 0xff;
@@ -289,6 +289,17 @@ GlyphUnit::~GlyphUnit()
                FT_Done_FreeType(freetype_library);
 }
 
+static inline void to_mono(VFrame *data)
+{
+       if( !data ) return;
+       int w = data->get_w(), h = data->get_h();
+       uint8_t **rows = data->get_rows();
+       for( int y=0; y<h; ++y ) {
+               uint8_t *dp = rows[y];
+               for( int x=0; x<w; ++x,++dp ) *dp = *dp >= 0x80 ? 0xff : 0;
+       }
+}
+
 void GlyphUnit::process_package(LoadPackage *package)
 {
        GlyphPackage *pkg = (GlyphPackage*)package;
@@ -491,6 +502,11 @@ printf("GlyphUnit::process_package 1 glyph not found (%s) %04x, '%c'\n",
 
 //printf("GlyphUnit::process_package 2\n");
                }
+
+               if( !(glyph->style & FONT_ALIAS) ) {
+                       to_mono(glyph->data);
+                       to_mono(glyph->data_stroke);
+               }
        }
 }
 
@@ -841,6 +857,10 @@ TitleCurFixed::TitleCurFixed(TitleParser *parser, TitleMain *plugin)
  : TitleStack<int>(parser, 0)
 {
 }
+TitleCurAlias::TitleCurAlias(TitleParser *parser, TitleMain *plugin)
+ : TitleStack<int>(parser, (plugin->config.style & FONT_ALIAS) ? 1 : 0)
+{
+}
 TitleCurSuper::TitleCurSuper(TitleParser *parser, TitleMain *plugin)
  : TitleStack<int>(parser, 0)
 {
@@ -859,6 +879,7 @@ TitleParser::TitleParser(TitleMain *plugin)
    cur_under(this, plugin),
    cur_blink(this, plugin),
    cur_fixed(this, plugin),
+   cur_alias(this, plugin),
    cur_super(this, plugin)
 {
        bfr = out = plugin->config.wtext;
@@ -1578,6 +1599,14 @@ int TitleCurFixed::set(const char *txt)
        return 0;
 }
 
+int TitleCurAlias::set(const char *txt)
+{
+       int alias = !*txt ? 1 : strtol(txt,(char **)&txt,0);
+       if( *txt ) return 1;
+       push(alias);
+       return 0;
+}
+
 int TitleCurSuper::set(const char *txt)
 {
        int super = !*txt ? 1 : strtol(txt,(char **)&txt,0);
@@ -1611,6 +1640,7 @@ int TitleParser::set_attributes(int ret)
         if( !strcmp(id,KW_UL) )     return ret>1 ? cur_under.unset(text)  : cur_under.set(text);
         if( !strcmp(id,KW_BLINK) )  return ret>1 ? cur_blink.unset(text)  : cur_blink.set(text);
         if( !strcmp(id,KW_FIXED) )  return ret>1 ? cur_fixed.unset(text)  : cur_fixed.set(text);
+        if( !strcmp(id,KW_ALIAS) )  return ret>1 ? cur_alias.unset(text)  : cur_alias.set(text);
         if( !strcmp(id,KW_SUP) )    return ret>1 ? cur_super.unset(text)  : cur_super.set(text);
        return 1;
 }
@@ -1644,6 +1674,8 @@ void TitleMain::load_glyphs()
                if( cur_bold ) cur_style |= BC_FONT_BOLD;
                int cur_italic  = wchrs.cur_italic;
                if( cur_italic ) cur_style |= BC_FONT_ITALIC;
+               int cur_alias  = wchrs.cur_alias;
+               if( cur_alias ) cur_style |= FONT_ALIAS;
                int cur_super = wchrs.cur_super;
                if( cur_super ) cur_size /= 2;
                int exists = 0;
@@ -1758,6 +1790,8 @@ int TitleMain::get_text()
                int cur_style = 0;
                int cur_bold  = wchrs.cur_bold;
                if( cur_bold ) cur_style |= BC_FONT_BOLD;
+               int cur_alias   = wchrs.cur_alias;
+               if( cur_alias ) cur_style |= FONT_ALIAS;
                int cur_italic  = wchrs.cur_italic;
                if( cur_italic ) cur_style |= BC_FONT_ITALIC;
                short nx = cur_nudge >> 16, ny = cur_nudge;
index faa37c5101b1cc2bed68ace015f2593aa1924c5f..e1d30ac88fac9faae5e8dab4236fa201880a126b 100644 (file)
@@ -34,6 +34,7 @@
 #define KW_UL     _("ul")
 #define KW_BLINK  _("blink")
 #define KW_FIXED  _("fixed")
+#define KW_ALIAS  _("alias")
 #define KW_SUP    _("sup")
 #define KW_PNG    _("png")
 
@@ -68,6 +69,7 @@ class TitleCurCaps;
 class TitleCurUnder;
 class TitleCurBlink;
 class TitleCurFixed;
+class TitleCurAlias;
 class TitleCurSuper;
 class TitleCurNudge;
 class TitleParser;
@@ -111,6 +113,7 @@ class TitleMain;
 // char types
 #define CHAR_GLYPH  0
 #define CHAR_IMAGE  1
+
 // flags
 #define FLAG_UNDER  0x0001
 #define FLAG_FIXED  0x0002
@@ -118,6 +121,8 @@ class TitleMain;
 #define FLAG_SUBER  0x0008
 #define FLAG_BLINK  0x0010
 
+#define FONT_ALIAS 0x08
+
 class TitleConfig
 {
 public:
@@ -481,6 +486,12 @@ public:
        int set(const char *txt);
 };
 
+class TitleCurAlias : public TitleStack<int> {
+public:
+       TitleCurAlias(TitleParser *parser, TitleMain *plugin);
+       int set(const char *txt);
+};
+
 class TitleCurSuper : public TitleStack<int> {
 public:
        TitleCurSuper(TitleParser *parser, TitleMain *plugin);
@@ -516,6 +527,7 @@ public:
        TitleCurUnder  cur_under;
        TitleCurBlink  cur_blink;
        TitleCurFixed  cur_fixed;
+       TitleCurAlias  cur_alias;
        TitleCurSuper  cur_super;
 
        TitleParser(TitleMain *main);
index 82979d12783d9243cab4b9688d735ec7615918ef..d3f20d2a651e2b46cc77cebc67285ccb61903cba 100644 (file)
@@ -266,6 +266,9 @@ void TitleWindow::create_objects()
                        eprintf("drag enabled, but compositor already grabbed\n");
        }
 
+       add_tool(alias = new TitleAlias(client, this, x, y+110));
+       if( alias->get_w() > w1 ) w1 = drag->get_w();
+
        x += w1 + margin;
        add_tool(justify_title = new BC_Title(x, y, _("Justify:")));
        add_tool(left = new TitleLeft(client, this, x, y + 20));
@@ -337,9 +340,9 @@ void TitleWindow::create_objects()
        if( fade_out->get_w() > w1 ) w1 = fade_out->get_w();
        x += w1 + margin;
 
-       add_tool(speed_title = new BC_Title(x, y1=y, _("Speed:")));
+       add_tool(speed_title = new BC_Title(x, y, _("Speed:")));
        w1 = speed_title->get_w();
-       y += speed_title->get_h() + 5;
+       y += speed_title->get_h() + 5;  y1 = y;
        speed = new TitleSpeed(client, this, x, y);
        speed->create_objects();
        if( speed->get_w() > w1 ) w1 = speed->get_w();
@@ -433,6 +436,7 @@ int TitleWindow::resize_event(int w, int h)
        italic->reposition_window(italic->get_x(), italic->get_y());
        bold->reposition_window(bold->get_x(), bold->get_y());
        drag->reposition_window(drag->get_x(), drag->get_y());
+       alias->reposition_window(alias->get_x(), alias->get_y());
        size_title->reposition_window(size_title->get_x(), size_title->get_y());
        size->reposition_window(size->get_x(), size->get_y());
        size_tumbler->reposition_window(size_tumbler->get_x(), size_tumbler->get_y());
@@ -734,6 +738,7 @@ void TitleWindow::update()
        title_h->update((int64_t)client->config.title_h);
        italic->update(client->config.style & BC_FONT_ITALIC);
        bold->update(client->config.style & BC_FONT_BOLD);
+       alias->update(client->config.style & FONT_ALIAS);
        size->update(client->config.size);
        motion->update(TitleMain::motion_to_text(client->config.motion_strategy));
        loop->update(client->config.loop);
@@ -841,6 +846,22 @@ int TitleSizeTumble::handle_down_event()
        return 1;
 }
 
+TitleAlias::TitleAlias(TitleMain *client, TitleWindow *window, int x, int y)
+ : BC_CheckBox(x, y, client->config.style & FONT_ALIAS, _("Alias"))
+{
+       this->client = client;
+       this->window = window;
+}
+
+int TitleAlias::handle_event()
+{
+       client->config.style =
+               (client->config.style & ~FONT_ALIAS) |
+                       (get_value() ? FONT_ALIAS : 0);
+       window->send_configure_change();
+       return 1;
+}
+
 TitleBold::TitleBold(TitleMain *client, TitleWindow *window, int x, int y)
  : BC_CheckBox(x, y, client->config.style & BC_FONT_BOLD, _("Bold"))
 {
@@ -1553,6 +1574,11 @@ void TitleCurPopup::create_objects()
        sub_menu->add_subitem("%s 10",item);
        sub_menu->add_subitem("%s 0",item);
        sub_menu->add_subitem("/%s",item);
+       add_item(cur_item = new TitleCurItem(this, item = KW_ALIAS));
+       cur_item->add_submenu(sub_menu = new TitleCurSubMenu(cur_item));
+       sub_menu->add_subitem("%s 1",item);
+       sub_menu->add_subitem("%s 0",item);
+       sub_menu->add_subitem("/%s",item);
        add_item(cur_item = new TitleCurItem(this, item = KW_SUP));
        cur_item->add_submenu(sub_menu = new TitleCurSubMenu(cur_item));
        sub_menu->add_subitem("%s 1",item);
index 9752b5f943f944f2ae87682b5edac64405ab51f4..def051b8670215b54b0b5099db9ab914d3e43edf 100644 (file)
@@ -38,6 +38,7 @@ class TitleInterlace;
 class TitleFontTumble;
 class TitleSizeTumble;
 class TitleItalic;
+class TitleAlias;
 class TitleBold;
 class TitleDrag;
 class TitleSize;
@@ -122,6 +123,7 @@ public:
        TitleStroker *stroker;
        BC_Title *style_title;
        TitleItalic *italic;
+       TitleAlias *alias;
        TitleBold *bold;
        TitleDrag *drag;
        TitleCurPopup *cur_popup;
@@ -207,7 +209,14 @@ public:
 };
 
 
-
+class TitleAlias : public BC_CheckBox
+{
+public:
+       TitleAlias(TitleMain *client, TitleWindow *window, int x, int y);
+       int handle_event();
+       TitleMain *client;
+       TitleWindow *window;
+};
 class TitleItalic : public BC_CheckBox
 {
 public: