From 3ad39dda113124e7e1bb11a808541e6311417863 Mon Sep 17 00:00:00 2001 From: Good Guy Date: Sat, 24 Mar 2018 15:09:14 -0600 Subject: [PATCH] descratch again reworked + icons, add agingtv plugin params, add alias chkbox in plugin titler, fix info for plugins, resource viewer vicon replay placement, pluginwindow font scale --- cinelerra-5.1/cinelerra/mwindow.C | 6 +- cinelerra-5.1/cinelerra/pluginclient.C | 9 +- cinelerra-5.1/guicast/vicon.C | 12 +- cinelerra-5.1/picon/cinfinity/descratch.png | Bin 0 -> 11281 bytes cinelerra-5.1/picon/cinfinity2/descratch.png | Bin 0 -> 10630 bytes cinelerra-5.1/plugins/aging/aging.C | 591 +++++++++---------- cinelerra-5.1/plugins/aging/aging.h | 59 +- cinelerra-5.1/plugins/aging/agingwindow.C | 202 ++----- cinelerra-5.1/plugins/aging/agingwindow.h | 100 +--- cinelerra-5.1/plugins/descratch/descratch.C | 399 +++++++------ cinelerra-5.1/plugins/descratch/descratch.h | 32 +- cinelerra-5.1/plugins/titler/titler.C | 36 +- cinelerra-5.1/plugins/titler/titler.h | 12 + cinelerra-5.1/plugins/titler/titlerwindow.C | 30 +- cinelerra-5.1/plugins/titler/titlerwindow.h | 11 +- 15 files changed, 677 insertions(+), 822 deletions(-) create mode 100644 cinelerra-5.1/picon/cinfinity/descratch.png create mode 100644 cinelerra-5.1/picon/cinfinity2/descratch.png diff --git a/cinelerra-5.1/cinelerra/mwindow.C b/cinelerra-5.1/cinelerra/mwindow.C index 38e37d2f..ff4de507 100644 --- a/cinelerra-5.1/cinelerra/mwindow.C +++ b/cinelerra-5.1/cinelerra/mwindow.C @@ -746,7 +746,7 @@ void MWindow::add_plugins(ArrayList &plugins) void MWindow::init_plugin_tips(ArrayList &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 &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 &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); diff --git a/cinelerra-5.1/cinelerra/pluginclient.C b/cinelerra-5.1/cinelerra/pluginclient.C index aaec69d8..417dd917 100644 --- a/cinelerra-5.1/cinelerra/pluginclient.C +++ b/cinelerra-5.1/cinelerra/pluginclient.C @@ -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; } diff --git a/cinelerra-5.1/guicast/vicon.C b/cinelerra-5.1/guicast/vicon.C index 031e9530..2bfedd92 100644 --- a/cinelerra-5.1/guicast/vicon.C +++ b/cinelerra-5.1/guicast/vicon.C @@ -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 index 0000000000000000000000000000000000000000..cd2edb6c0211dbfb65b561a783a7b40b5ae091f9 GIT binary patch literal 11281 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 Hu0mjfb=IWE literal 0 HcmV?d00001 diff --git a/cinelerra-5.1/picon/cinfinity2/descratch.png b/cinelerra-5.1/picon/cinfinity2/descratch.png new file mode 100644 index 0000000000000000000000000000000000000000..926c63c818ebd8e9d3d6a091100cc201ef8a9c46 GIT binary patch literal 10630 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 g-cHvvE#i;=e-1Ft! #include - - - - - 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() { } - - diff --git a/cinelerra-5.1/plugins/aging/aging.h b/cinelerra-5.1/plugins/aging/aging.h index 8be9fd85..534beb80 100644 --- a/cinelerra-5.1/plugins/aging/aging.h +++ b/cinelerra-5.1/plugins/aging/aging.h @@ -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]; }; diff --git a/cinelerra-5.1/plugins/aging/agingwindow.C b/cinelerra-5.1/plugins/aging/agingwindow.C index 213d998e..9c702d7e 100644 --- a/cinelerra-5.1/plugins/aging/agingwindow.C +++ b/cinelerra-5.1/plugins/aging/agingwindow.C @@ -23,22 +23,10 @@ #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; } - - - - - diff --git a/cinelerra-5.1/plugins/aging/agingwindow.h b/cinelerra-5.1/plugins/aging/agingwindow.h index 9d593b4e..5f0bce88 100644 --- a/cinelerra-5.1/plugins/aging/agingwindow.h +++ b/cinelerra-5.1/plugins/aging/agingwindow.h @@ -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 diff --git a/cinelerra-5.1/plugins/descratch/descratch.C b/cinelerra-5.1/plugins/descratch/descratch.C index 8375510f..b94fc9da 100644 --- a/cinelerra-5.1/plugins/descratch/descratch.C +++ b/cinelerra-5.1/plugins/descratch/descratch.C @@ -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 + 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 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; + 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 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; i0; ) *(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= 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= 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 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; 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; + 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) 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")) { diff --git a/cinelerra-5.1/plugins/descratch/descratch.h b/cinelerra-5.1/plugins/descratch/descratch.h index b6c726dd..841899f5 100644 --- a/cinelerra-5.1/plugins/descratch/descratch.h +++ b/cinelerra-5.1/plugins/descratch/descratch.h @@ -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: diff --git a/cinelerra-5.1/plugins/titler/titler.C b/cinelerra-5.1/plugins/titler/titler.C index 117e279e..9056bc19 100644 --- a/cinelerra-5.1/plugins/titler/titler.C +++ b/cinelerra-5.1/plugins/titler/titler.C @@ -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= 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(parser, 0) { } +TitleCurAlias::TitleCurAlias(TitleParser *parser, TitleMain *plugin) + : TitleStack(parser, (plugin->config.style & FONT_ALIAS) ? 1 : 0) +{ +} TitleCurSuper::TitleCurSuper(TitleParser *parser, TitleMain *plugin) : TitleStack(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; diff --git a/cinelerra-5.1/plugins/titler/titler.h b/cinelerra-5.1/plugins/titler/titler.h index faa37c51..e1d30ac8 100644 --- a/cinelerra-5.1/plugins/titler/titler.h +++ b/cinelerra-5.1/plugins/titler/titler.h @@ -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 { +public: + TitleCurAlias(TitleParser *parser, TitleMain *plugin); + int set(const char *txt); +}; + class TitleCurSuper : public TitleStack { 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); diff --git a/cinelerra-5.1/plugins/titler/titlerwindow.C b/cinelerra-5.1/plugins/titler/titlerwindow.C index 82979d12..d3f20d2a 100644 --- a/cinelerra-5.1/plugins/titler/titlerwindow.C +++ b/cinelerra-5.1/plugins/titler/titlerwindow.C @@ -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); diff --git a/cinelerra-5.1/plugins/titler/titlerwindow.h b/cinelerra-5.1/plugins/titler/titlerwindow.h index 9752b5f9..def051b8 100644 --- a/cinelerra-5.1/plugins/titler/titlerwindow.h +++ b/cinelerra-5.1/plugins/titler/titlerwindow.h @@ -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: -- 2.26.2