X-Git-Url: http://git.cinelerra-gg.org/git/?p=goodguy%2Fhistory.git;a=blobdiff_plain;f=cinelerra-5.1%2Fplugins%2Fcrikey%2Fcrikey.C;h=b3e7592bddcd655eaa5494cbf4697b01ebea9041;hp=ccbb216a34ca180373edfe4a14050e0e2ca1743b;hb=9d832a1fff11b11aaa1108c460690ed05e2bdc05;hpb=63ced327c156ea7fe4448a18b0b1b0f2571dce7e diff --git a/cinelerra-5.1/plugins/crikey/crikey.C b/cinelerra-5.1/plugins/crikey/crikey.C index ccbb216a..b3e7592b 100644 --- a/cinelerra-5.1/plugins/crikey/crikey.C +++ b/cinelerra-5.1/plugins/crikey/crikey.C @@ -25,8 +25,9 @@ #include "arraylist.h" #include "bccmodels.h" -#include "cicolors.h" +#include "bccolors.h" #include "clip.h" +#include "edlsession.h" #include "filexml.h" #include "crikey.h" #include "crikeywindow.h" @@ -48,25 +49,42 @@ void crikey_pgm(const char *fn,VFrame *vfrm) } #endif +CriKeyPoint::CriKeyPoint(int t, int e, float x, float y) +{ + this->t = t; this->e = e; this->x = x; this->y = y; +} +CriKeyPoint::~CriKeyPoint() +{ +} + CriKeyConfig::CriKeyConfig() { color = 0x000000; threshold = 0.5f; draw_mode = DRAW_ALPHA; - key_mode = KEY_SEARCH; - point_x = point_y = 0; drag = 0; + selected = 0; +} +CriKeyConfig::~CriKeyConfig() +{ + points.remove_all_objects(); } int CriKeyConfig::equivalent(CriKeyConfig &that) { - return this->color != that.color || - !EQUIV(this->threshold, that.threshold) || - this->draw_mode != that.draw_mode || - this->key_mode != that.key_mode || - !EQUIV(this->point_x, that.point_x) || - !EQUIV(this->point_y, that.point_y) || - this->drag != that.drag ? 0 : 1; + if( this->color != that.color ) return 0; + if( !EQUIV(this->threshold, that.threshold) ) return 0; + if( this->draw_mode != that.draw_mode ) return 0; + if( this->drag != that.drag ) return 0; + if( this->points.size() != that.points.size() ) return 0; + for( int i=0, n=points.size(); ipoints[i], *bp = that.points[i]; + if( ap->t != bp->t ) return 0; + if( ap->e != bp->e ) return 0; + if( !EQUIV(ap->x, bp->x) ) return 0; + if( !EQUIV(ap->y, bp->y) ) return 0; + } + return 1; } void CriKeyConfig::copy_from(CriKeyConfig &that) @@ -74,33 +92,47 @@ void CriKeyConfig::copy_from(CriKeyConfig &that) this->color = that.color; this->threshold = that.threshold; this->draw_mode = that.draw_mode; - this->key_mode = that.key_mode; - this->point_x = that.point_x; - this->point_y = that.point_y; this->drag = that.drag; + this->selected = that.selected; + + points.remove_all_objects(); + for( int i=0,n=that.points.size(); it, pt->e, pt->x, pt->y); + } } void CriKeyConfig::interpolate(CriKeyConfig &prev, CriKeyConfig &next, long prev_frame, long next_frame, long current_frame) { - copy_from(prev); + this->color = prev.color; + this->draw_mode = prev.draw_mode; + this->drag = prev.drag; + this->selected = prev.selected; + double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame); double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame); this->threshold = prev.threshold * prev_scale + next.threshold * next_scale; - switch( prev.key_mode ) { - case KEY_POINT: { - this->point_x = prev.point_x * prev_scale + next.point_x * next_scale; - this->point_y = prev.point_y * prev_scale + next.point_y * next_scale; - break; } - case KEY_SEARCH: - case KEY_SEARCH_ALL: { - float prev_target[3]; set_target(0, prev.color, prev_target); - float next_target[3]; set_target(0, next.color, next_target); - float target[3]; // interpolates rgb components - for( int i=0; i<3; ++i ) - target[i] = prev_target[i] * prev_scale + next_target[i] * next_scale; - set_color(0, target, this->color); - break; } + // interpolate rgb components + float prev_target[3]; set_target(0, prev.color, prev_target); + float next_target[3]; set_target(0, next.color, next_target); + float target[3]; + for( int i=0; i<3; ++i ) + target[i] = prev_target[i] * prev_scale + next_target[i] * next_scale; + set_color(0, target, this->color); + + points.remove_all_objects(); + int prev_sz = prev.points.size(), next_sz = next.points.size(); + for( int i=0; ix, y = pt->y; + int k = next_sz; // associated by tag id in next + while( --k >= 0 && pt->t != (nt=next.points[k])->t ); + if( k >= 0 ) { + x = x * prev_scale + nt->x * next_scale; + y = y * prev_scale + nt->y * next_scale; + } + add_point(pt->t, pt->e, x, y); } } @@ -108,7 +140,25 @@ void CriKeyConfig::limits() { bclamp(threshold, 0.0f, 1.0f); bclamp(draw_mode, 0, DRAW_MODES-1); - bclamp(key_mode, 0, KEY_MODES-1); +} + +int CriKeyConfig::add_point(int t, int e, float x, float y) +{ + int k = points.size(); + if( t < 0 ) { + t = 0; + for( int i=k; --i>=0; ) { + int n = points[i]->t; + if( n >= t ) t = n + 1; + } + } + points.append(new CriKeyPoint(t, e, x, y)); + return k; +} + +void CriKeyConfig::del_point(int i) +{ + points.remove_object_number(i); } @@ -127,20 +177,19 @@ class FillRegion stack.remove(); } - int w, h, threshold; + int w, h; uint8_t *data, *mask; bool edge_pixel(uint8_t *dp) { return *dp; } public: void fill(int x, int y); - void set_threshold(float v) { threshold = v; } + void run(); FillRegion(VFrame *d, VFrame *m); }; FillRegion::FillRegion(VFrame *d, VFrame *m) { - threshold = 128; w = d->get_w(); h = d->get_h(); data = d->get_data(); @@ -150,27 +199,37 @@ FillRegion::FillRegion(VFrame *d, VFrame *m) void FillRegion::fill(int x, int y) { push(y, x, x); +} - do { - int ilt, irt, lt, rt; +void FillRegion::run() +{ + while( stack.size() > 0 ) { + int y, ilt, irt; pop(y, ilt, irt); int ofs = y*w + ilt; - uint8_t *idp = data + ofs, *dp; - uint8_t *imp = mask + ofs, *mp; + uint8_t *idp = data + ofs; + uint8_t *imp = mask + ofs; for( int x=ilt; x<=irt; ++x,++imp,++idp ) { - if( !*imp || edge_pixel(idp) ) continue; + if( !*imp ) continue; *imp = 0; - lt = rt = x; - dp = idp; mp = imp; - for( int i=lt; --i>=0; lt=i,*mp=0 ) - if( !*--mp || edge_pixel(--dp) ) break; - dp = idp; mp = imp; - for( int i=rt; ++i< w; rt=i,*mp=0 ) - if( !*++mp || edge_pixel(++dp) ) break; + if( edge_pixel(idp) ) continue; + int lt = x, rt = x; + uint8_t *ldp = idp, *lmp = imp; + for( int i=lt; --i>=0; ) { + if( !*--lmp ) break; + *lmp = 0; lt = i; + if( edge_pixel(--ldp) ) break; + } + uint8_t *rdp = idp, *rmp = imp; + for( int i=rt; ++i< w; rt=i,*rmp=0 ) { + if( !*++rmp ) break; + *rmp = 0; rt = i; + if( edge_pixel(++rdp) ) break; + } if( y+1 < h ) push(y+1, lt, rt); if( y-1 >= 0 ) push(y-1, lt, rt); } - } while( stack.size() > 0 ); + } } @@ -180,7 +239,6 @@ CriKey::CriKey(PluginServer *server) engine = 0; msk = 0; dst = 0; - diff_pixel = 0; } CriKey::~CriKey() @@ -241,61 +299,20 @@ void CriKey::get_color(int x, int y) } } -float CriKey::diff_uint8(uint8_t *dp) -{ - float scale = 1./255., v = 0; - for( int i=0; iget_rows(); - for( int y=0; y*diff_pixel)(sp); - if( v >= mv ) continue; - mv = v; ix = x; iy = y; - } - } -} -bool CriKey::find_key(int &ix, int &iy, float thr) -{ - uint8_t **src_rows = src->get_rows(); - uint8_t **msk_rows = msk->get_rows(); - int x = ix, y = iy; - for( ; y*diff_pixel)(sp); - if( v < thr ) { - ix = x; iy = y; - return true; - } - } - x = 0; - } - return false; -} - const char* CriKey::plugin_title() { return _("CriKey"); } int CriKey::is_realtime() { return 1; } NEW_WINDOW_MACRO(CriKey, CriKeyWindow); LOAD_CONFIGURATION_MACRO(CriKey, CriKeyConfig) +int CriKey::new_point() +{ + EDLSession *session = get_edlsession(); + float x = !session ? 0.f : session->output_w / 2.f; + float y = !session ? 0.f : session->output_h / 2.f; + return config.add_point(-1, 0, x, y); +} + void CriKey::save_data(KeyFrame *keyframe) { FileXML output; @@ -307,15 +324,26 @@ void CriKey::save_data(KeyFrame *keyframe) output.tag.set_property("COLOR", config.color); output.tag.set_property("THRESHOLD", config.threshold); output.tag.set_property("DRAW_MODE", config.draw_mode); - output.tag.set_property("KEY_MODE", config.key_mode); - output.tag.set_property("POINT_X", config.point_x); - output.tag.set_property("POINT_Y", config.point_y); output.tag.set_property("DRAG", config.drag); + output.tag.set_property("SELECTED", config.selected); output.append_tag(); output.append_newline(); output.tag.set_title("/CRIKEY"); output.append_tag(); output.append_newline(); + for( int i=0, n = config.points.size(); it); + output.tag.set_title(point+1); + output.tag.set_property("E", pt->e); + output.tag.set_property("X", pt->x); + output.tag.set_property("Y", pt->y); + output.append_tag(); + output.tag.set_title(point+0); + output.append_tag(); + output.append_newline(); + } output.terminate_string(); } @@ -323,24 +351,28 @@ void CriKey::read_data(KeyFrame *keyframe) { FileXML input; input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data())); + config.points.remove_all_objects(); int result = 0; while( !(result=input.read_tag()) ) { - if(input.tag.title_is("CRIKEY")) { + if( input.tag.title_is("CRIKEY") ) { config.color = input.tag.get_property("COLOR", config.color); config.threshold = input.tag.get_property("THRESHOLD", config.threshold); config.draw_mode = input.tag.get_property("DRAW_MODE", config.draw_mode); - config.key_mode = input.tag.get_property("KEY_MODE", config.key_mode); - config.point_x = input.tag.get_property("POINT_X", config.point_x); - config.point_y = input.tag.get_property("POINT_Y", config.point_y); config.drag = input.tag.get_property("DRAG", config.drag); + config.selected = input.tag.get_property("SELECTED", 0); config.limits(); } - else if(input.tag.title_is("/CRIKEY")) { - result = 1; + else if( !strncmp(input.tag.get_title(),"POINT_",6) ) { + int t = atoi(input.tag.get_title() + 6); + int e = input.tag.get_property("E", 0); + float x = input.tag.get_property("X", 0.f); + float y = input.tag.get_property("Y", 0.f); + config.add_point(t, e, x, y); } } + if( !config.points.size() ) new_point(); } void CriKey::update_gui() @@ -488,6 +520,24 @@ void CriKey::draw_mask(VFrame *msk) } } +void CriKey::draw_point(VFrame *src, CriKeyPoint *pt) +{ + int d = bmax(w,h) / 200 + 2; + int r = d/2+1, x = pt->x, y = pt->y; + src->draw_smooth(x-r,y+0, x-r, y-r, x+0,y-r); + src->draw_smooth(x+0,y-r, x+r, y-r, x+r,y+0); + src->draw_smooth(x+r,y+0, x+r, y+r, x+0,y+r); + src->draw_smooth(x+0,y+r, x-r, y+r, x-r,y+0); + if( pt->e ) { + src->set_pixel_color(RED); + src->draw_x(pt->x, pt->y, d); + } + else { + src->set_pixel_color(BLUE); + src->draw_t(pt->x, pt->y, d); + } +} + int CriKey::process_buffer(VFrame *frame, int64_t start_position, double frame_rate) { load_configuration(); @@ -499,26 +549,17 @@ int CriKey::process_buffer(VFrame *frame, int64_t start_position, double frame_r if( comp > 3 ) comp = 3; is_yuv = BC_CModels::is_yuv(color_model); is_float = BC_CModels::is_float(color_model); - diff_pixel = is_float ? &CriKey::diff_float : &CriKey::diff_uint8; read_frame(src, 0, start_position, frame_rate, 0); - switch( config.key_mode ) { - case KEY_SEARCH: - case KEY_SEARCH_ALL: - set_target(is_yuv, config.color, target); - break; - case KEY_POINT: - get_color(config.point_x, config.point_y); - break; - } + set_target(is_yuv, config.color, target); if( dst && ( dst->get_w() != w || src->get_h() != h ) ) { delete dst; dst = 0; } if( !dst ) dst = new VFrame(w, h, BC_A8); - memset(dst->get_data(), 0x00, dst->get_data_size()); + dst->clear_frame(); if( !engine ) engine = new CriKeyEngine(this, @@ -532,47 +573,41 @@ int CriKey::process_buffer(VFrame *frame, int64_t start_position, double frame_r if( h1 > 0 ) for( int x=0; xget_w() != w || msk->get_h() != h ) ) { - delete msk; msk = 0; - } - if( !msk ) - msk = new VFrame(w, h, BC_A8); - memset(msk->get_data(), 0xff, msk->get_data_size()); - - FillRegion fill_region(dst, msk); - fill_region.set_threshold(config.threshold); - - int x = 0, y = 0; - switch( config.key_mode ) { - case KEY_SEARCH: - min_key(x, y); - fill_region.fill(x, y); - break; - case KEY_SEARCH_ALL: - while( find_key(x, y, config.threshold) ) { - fill_region.fill(x, y); - ++x; + if( config.draw_mode != DRAW_EDGE ) { + if( msk && ( msk->get_w() != w || msk->get_h() != h ) ) { + delete msk; msk = 0; } - break; - case KEY_POINT: - x = config.point_x, y = config.point_y; - if( x >= 0 && x < w && y >= 0 && y < h ) - fill_region.fill(x, y); - break; - } + if( !msk ) + msk = new VFrame(w, h, BC_A8); + memset(msk->get_data(), 0xff, msk->get_data_size()); + + FillRegion fill_region(dst, msk); + for( int i=0, n=config.points.size(); ie ) continue; + float x = pt->x, y = pt->y; + if( x >= 0 && x < w && y >= 0 && y < h ) + fill_region.fill(x, y); + } + fill_region.run(); + //crikey_pgm("/tmp/msk.pgm",msk); - if( config.draw_mode == DRAW_MASK ) { - draw_mask(msk); - return 0; + if( config.draw_mode == DRAW_MASK ) + draw_mask(msk); + else + draw_alpha(msk); } + else + draw_mask(dst); - draw_alpha(msk); + if( config.drag ) { + for( int i=0, n=config.points.size(); iset_pixel_color(config.selected == i ? GREEN : WHITE); + draw_point(src, pt); + } + } return 0; } @@ -618,10 +653,10 @@ LoadClient* CriKeyEngine::new_client() } \ v = 0; \ float a = bmin(bmin(a00, a01), bmin(a10, a11)); \ - if( a < threshold ) continue; \ + if( a > threshold ) continue; \ float b = bmax(bmax(a00, a01), bmax(a10, a11)); \ - if( b <= threshold ) continue; \ - v = (b-a)*254 + 1; \ + if( threshold >= b ) continue; \ + v = 255; \ } \ } \ } break