From 680d2000be2db33da1e2733461854158067f5862 Mon Sep 17 00:00:00 2001 From: Good Guy Date: Fri, 7 Jul 2017 12:00:08 -0600 Subject: [PATCH 1/1] affine + perspective plugin rework, info popup tweaks --- cinelerra-5.1/cinelerra/affine.C | 1242 ++++++----------- cinelerra-5.1/cinelerra/affine.h | 32 +- cinelerra-5.1/cinelerra/assetedit.C | 6 +- cinelerra-5.1/cinelerra/assetpopup.C | 13 +- cinelerra-5.1/cinelerra/clipedit.C | 1 + .../plugins/perspective/perspective.C | 756 ++++------ .../plugins/perspective/perspective.h | 112 +- 7 files changed, 753 insertions(+), 1409 deletions(-) diff --git a/cinelerra-5.1/cinelerra/affine.C b/cinelerra-5.1/cinelerra/affine.C index 09f81f2e..f5f90a7c 100644 --- a/cinelerra-5.1/cinelerra/affine.C +++ b/cinelerra-5.1/cinelerra/affine.C @@ -73,22 +73,16 @@ void AffineMatrix::scale(double x, double y) void AffineMatrix::multiply(AffineMatrix *dst) { - int i, j; AffineMatrix tmp; - double t1, t2, t3; - - for (i = 0; i < 3; i++) - { - t1 = values[i][0]; - t2 = values[i][1]; - t3 = values[i][2]; - for (j = 0; j < 3; j++) - { + + for( int i=0; i<3; ++i ) { + double t1 = values[i][0], t2 = values[i][1], t3 = values[i][2]; + for( int j=0; j<3; ++j ) { tmp.values[i][j] = t1 * dst->values[0][j]; tmp.values[i][j] += t2 * dst->values[1][j]; tmp.values[i][j] += t3 * dst->values[2][j]; } - } + } dst->copy_from(&tmp); } @@ -97,11 +91,11 @@ double AffineMatrix::determinant() double determinant; determinant = - values[0][0] * (values[1][1] * values[2][2] - values[1][2] * values[2][1]); + values[0][0] * (values[1][1] * values[2][2] - values[1][2] * values[2][1]); determinant -= - values[1][0] * (values[0][1] * values[2][2] - values[0][2] * values[2][1]); + values[1][0] * (values[0][1] * values[2][2] - values[0][2] * values[2][1]); determinant += - values[2][0] * (values[0][1] * values[1][2] - values[0][2] * values[1][1]); + values[2][0] * (values[0][1] * values[1][2] - values[0][2] * values[1][1]); return determinant; } @@ -113,36 +107,36 @@ void AffineMatrix::invert(AffineMatrix *dst) det_1 = determinant(); if(det_1 == 0.0) - return; + return; det_1 = 1.0 / det_1; dst->values[0][0] = - (values[1][1] * values[2][2] - values[1][2] * values[2][1]) * det_1; + (values[1][1] * values[2][2] - values[1][2] * values[2][1]) * det_1; dst->values[1][0] = - - (values[1][0] * values[2][2] - values[1][2] * values[2][0]) * det_1; + - (values[1][0] * values[2][2] - values[1][2] * values[2][0]) * det_1; dst->values[2][0] = - (values[1][0] * values[2][1] - values[1][1] * values[2][0]) * det_1; + (values[1][0] * values[2][1] - values[1][1] * values[2][0]) * det_1; dst->values[0][1] = - - (values[0][1] * values[2][2] - values[0][2] * values[2][1] ) * det_1; + - (values[0][1] * values[2][2] - values[0][2] * values[2][1] ) * det_1; dst->values[1][1] = - (values[0][0] * values[2][2] - values[0][2] * values[2][0]) * det_1; + (values[0][0] * values[2][2] - values[0][2] * values[2][0]) * det_1; dst->values[2][1] = - - (values[0][0] * values[2][1] - values[0][1] * values[2][0]) * det_1; + - (values[0][0] * values[2][1] - values[0][1] * values[2][0]) * det_1; dst->values[0][2] = - (values[0][1] * values[1][2] - values[0][2] * values[1][1]) * det_1; + (values[0][1] * values[1][2] - values[0][2] * values[1][1]) * det_1; dst->values[1][2] = - - (values[0][0] * values[1][2] - values[0][2] * values[1][0]) * det_1; + - (values[0][0] * values[1][2] - values[0][2] * values[1][0]) * det_1; dst->values[2][2] = - (values[0][0] * values[1][1] - values[0][1] * values[1][0]) * det_1; + (values[0][0] * values[1][1] - values[0][1] * values[1][0]) * det_1; } void AffineMatrix::copy_from(AffineMatrix *src) @@ -158,11 +152,7 @@ void AffineMatrix::transform_point(float x, double w; w = values[2][0] * x + values[2][1] * y + values[2][2]; - - if (w == 0.0) - w = 1.0; - else - w = 1.0 / w; + w = !w ? 1 : 1/w; *newx = (values[0][0] * x + values[0][1] * y + values[0][2]) * w; *newy = (values[1][0] * x + values[1][1] * y + values[1][2]) * w; @@ -203,18 +193,9 @@ AffineUnit::AffineUnit(AffineEngine *server) void AffineUnit::calculate_matrix( - double in_x1, - double in_y1, - double in_x2, - double in_y2, - double out_x1, - double out_y1, - double out_x2, - double out_y2, - double out_x3, - double out_y3, - double out_x4, - double out_y4, + double in_x1, double in_y1, double in_x2, double in_y2, + double out_x1, double out_y1, double out_x2, double out_y2, + double out_x3, double out_y3, double out_x4, double out_y4, AffineMatrix *result) { AffineMatrix matrix; @@ -223,65 +204,57 @@ void AffineUnit::calculate_matrix( scalex = scaley = 1.0; - if((in_x2 - in_x1) > 0) - scalex = 1.0 / (double)(in_x2 - in_x1); + if( (in_x2 - in_x1) > 0 ) + scalex = 1.0 / (double)(in_x2 - in_x1); - if((in_y2 - in_y1) > 0) - scaley = 1.0 / (double)(in_y2 - in_y1); + if( (in_y2 - in_y1) > 0 ) + scaley = 1.0 / (double)(in_y2 - in_y1); /* Determine the perspective transform that maps from * the unit cube to the transformed coordinates */ - double dx1, dx2, dx3, dy1, dy2, dy3; - double det1, det2; + double dx1, dx2, dx3, dy1, dy2, dy3; + double det1, det2; - dx1 = out_x2 - out_x4; - dx2 = out_x3 - out_x4; - dx3 = out_x1 - out_x2 + out_x4 - out_x3; + dx1 = out_x2 - out_x4; + dx2 = out_x3 - out_x4; + dx3 = out_x1 - out_x2 + out_x4 - out_x3; - dy1 = out_y2 - out_y4; - dy2 = out_y3 - out_y4; - dy3 = out_y1 - out_y2 + out_y4 - out_y3; + dy1 = out_y2 - out_y4; + dy2 = out_y3 - out_y4; + dy3 = out_y1 - out_y2 + out_y4 - out_y3; // printf("AffineUnit::calculate_matrix %f %f %f %f %f %f\n", -// dx1, -// dx2, -// dx3, -// dy1, -// dy2, -// dy3 -// ); +// dx1, dx2, dx3, dy1, dy2, dy3 ); /* Is the mapping affine? */ - if((dx3 == 0.0) && (dy3 == 0.0)) - { - matrix.values[0][0] = out_x2 - out_x1; - matrix.values[0][1] = out_x4 - out_x2; - matrix.values[0][2] = out_x1; - matrix.values[1][0] = out_y2 - out_y1; - matrix.values[1][1] = out_y4 - out_y2; - matrix.values[1][2] = out_y1; - matrix.values[2][0] = 0.0; - matrix.values[2][1] = 0.0; - } - else - { - det1 = dx3 * dy2 - dy3 * dx2; - det2 = dx1 * dy2 - dy1 * dx2; - matrix.values[2][0] = det1 / det2; - det1 = dx1 * dy3 - dy1 * dx3; - det2 = dx1 * dy2 - dy1 * dx2; - matrix.values[2][1] = det1 / det2; - - matrix.values[0][0] = out_x2 - out_x1 + matrix.values[2][0] * out_x2; - matrix.values[0][1] = out_x3 - out_x1 + matrix.values[2][1] * out_x3; - matrix.values[0][2] = out_x1; - - matrix.values[1][0] = out_y2 - out_y1 + matrix.values[2][0] * out_y2; - matrix.values[1][1] = out_y3 - out_y1 + matrix.values[2][1] * out_y3; - matrix.values[1][2] = out_y1; - } - - matrix.values[2][2] = 1.0; + if((dx3 == 0.0) && (dy3 == 0.0)) { + matrix.values[0][0] = out_x2 - out_x1; + matrix.values[0][1] = out_x4 - out_x2; + matrix.values[0][2] = out_x1; + matrix.values[1][0] = out_y2 - out_y1; + matrix.values[1][1] = out_y4 - out_y2; + matrix.values[1][2] = out_y1; + matrix.values[2][0] = 0.0; + matrix.values[2][1] = 0.0; + } + else { + det1 = dx3 * dy2 - dy3 * dx2; + det2 = dx1 * dy2 - dy1 * dx2; + matrix.values[2][0] = det1 / det2; + det1 = dx1 * dy3 - dy1 * dx3; + det2 = dx1 * dy2 - dy1 * dx2; + matrix.values[2][1] = det1 / det2; + + matrix.values[0][0] = out_x2 - out_x1 + matrix.values[2][0] * out_x2; + matrix.values[0][1] = out_x3 - out_x1 + matrix.values[2][1] * out_x3; + matrix.values[0][2] = out_x1; + + matrix.values[1][0] = out_y2 - out_y1 + matrix.values[2][0] * out_y2; + matrix.values[1][1] = out_y3 - out_y1 + matrix.values[2][1] * out_y3; + matrix.values[1][2] = out_y1; + } + + matrix.values[2][2] = 1.0; // printf("AffineUnit::calculate_matrix 1 %f %f\n", dx3, dy3); // matrix.dump(); @@ -290,25 +263,29 @@ void AffineUnit::calculate_matrix( result->translate(-in_x1, -in_y1); result->scale(scalex, scaley); matrix.multiply(result); -// double test[3][3] = { { 0.0896, 0.0, 0.0 }, -// { 0.0, 0.0896, 0.0 }, -// { -0.00126, 0.0, 1.0 } }; +// double test[3][3] = +// { { 0.0896, 0.0, 0.0 }, { 0.0, 0.0896, 0.0 }, { -0.00126, 0.0, 1.0 } }; // memcpy(&result->values[0][0], test, sizeof(test)); // printf("AffineUnit::calculate_matrix 4 %p\n", result); // result->dump(); - - } static inline float transform_cubic(float dx, - float jm1, float j, float jp1, float jp2) + float p0, float p1, float p2, float p3) { /* Catmull-Rom - not bad */ - float result = ((( ( - jm1 + 3.0 * j - 3.0 * jp1 + jp2 ) * dx + - ( 2.0 * jm1 - 5.0 * j + 4.0 * jp1 - jp2 ) ) * dx + - ( - jm1 + jp1 ) ) * dx + (j + j) ) / 2.0; -// printf("%f %f %f %f %f\n", result, jm1, j, jp1, jp2); - return result; + float result = ((( (- p0 + 3*p1 - 3*p2 + p3) * dx + + ( 2*p0 - 5*p1 + 4*p2 - p3 ) ) * dx + + ( - p0 + p2 ) ) * dx + (p1 + p1) ) / 2; +// printf("%f %f %f %f %f\n", result, p0, p1, p2, p3); + return result; +} + +static inline float transform_linear(float dx, + float p1, float p2) +{ + float result = p1 * (1-dx) + p2 * dx; + return result; } @@ -339,11 +316,10 @@ void AffineUnit::process_package(LoadPackage *package) // Calculate real coords float out_x1, out_y1, out_x2, out_y2, out_x3, out_y3, out_x4, out_y4; - if(server->mode == AffineEngine::STRETCH || - server->mode == AffineEngine::PERSPECTIVE || - server->mode == AffineEngine::ROTATE || - server->mode == AffineEngine::TRANSFORM) - { + if( server->mode == AffineEngine::STRETCH || + server->mode == AffineEngine::PERSPECTIVE || + server->mode == AffineEngine::ROTATE || + server->mode == AffineEngine::TRANSFORM ) { out_x1 = (float)server->in_x + (float)server->x1 * server->in_w / 100; out_y1 = (float)server->in_y + (float)server->y1 * server->in_h / 100; out_x2 = (float)server->in_x + (float)server->x2 * server->in_w / 100; @@ -353,8 +329,7 @@ void AffineUnit::process_package(LoadPackage *package) out_x4 = (float)server->in_x + (float)server->x4 * server->in_w / 100; out_y4 = (float)server->in_y + (float)server->y4 * server->in_h / 100; } - else - { + else { out_x1 = (float)server->in_x + (float)server->x1 * server->in_w / 100; out_y1 = server->in_y; out_x2 = out_x1 + server->in_w; @@ -368,9 +343,8 @@ void AffineUnit::process_package(LoadPackage *package) // Rotation with OpenGL uses a simple quad. - if(server->mode == AffineEngine::ROTATE && - server->use_opengl) - { + if( server->mode == AffineEngine::ROTATE && + server->use_opengl ) { #ifdef HAVE_GL out_x1 -= pivot_offset_x; out_y1 -= pivot_offset_y; out_x2 -= pivot_offset_x; out_y2 -= pivot_offset_y; @@ -416,11 +390,10 @@ void AffineUnit::process_package(LoadPackage *package) #endif } else - if(server->mode == AffineEngine::PERSPECTIVE || - server->mode == AffineEngine::SHEER || - server->mode == AffineEngine::ROTATE || - server->mode == AffineEngine::TRANSFORM) - { + if( server->mode == AffineEngine::PERSPECTIVE || + server->mode == AffineEngine::SHEER || + server->mode == AffineEngine::ROTATE || + server->mode == AffineEngine::TRANSFORM ) { AffineMatrix matrix; float temp; // swap points 3 & 4 @@ -435,40 +408,22 @@ void AffineUnit::process_package(LoadPackage *package) - if(server->mode != AffineEngine::TRANSFORM) - { - calculate_matrix( - server->in_x, - server->in_y, + if( server->mode != AffineEngine::TRANSFORM ) { + calculate_matrix( server->in_x, server->in_y, server->in_x + server->in_w, server->in_y + server->in_h, - out_x1, - out_y1, - out_x2, - out_y2, - out_x3, - out_y3, - out_x4, - out_y4, + out_x1, out_y1, out_x2, out_y2, + out_x3, out_y3, out_x4, out_y4, &matrix); } - else - { + else { matrix.copy_from(&server->matrix); } -// printf("AffineUnit::process_package %d\n%f %f %f\n%f %f %f\n%f %f %f\n", -// __LINE__, -// matrix.values[0][0], -// matrix.values[0][1], -// matrix.values[0][2], -// matrix.values[1][0], -// matrix.values[1][1], -// matrix.values[1][2], -// matrix.values[2][0], -// matrix.values[2][1], -// matrix.values[2][2]); - int interpolate = 1; +//printf("AffineUnit::process_package %d\n%f %f %f\n%f %f %f\n%f %f %f\n", __LINE__, +// matrix.values[0][0], matrix.values[0][1], matrix.values[0][2], +// matrix.values[1][0], matrix.values[1][1], matrix.values[1][2], +// matrix.values[2][0], matrix.values[2][1], matrix.values[2][2]); int reverse = !server->forward; float tx, ty, tw; float xinc, yinc, winc; @@ -477,22 +432,15 @@ void AffineUnit::process_package(LoadPackage *package) int itx = 0, ity = 0; int tx1 = 0, ty1 = 0, tx2 = 0, ty2 = 0; - if(reverse) - { + if(reverse) { m.copy_from(&matrix); m.invert(&im); matrix.copy_from(&im); } - else - { + else { matrix.invert(&m); } - - - - - float dx1 = 0, dy1 = 0; float dx2 = 0, dy2 = 0; float dx3 = 0, dy3 = 0; @@ -507,12 +455,8 @@ void AffineUnit::process_package(LoadPackage *package) // printf("AffineUnit::process_package %d use_opengl=%d\n", // __LINE__, server->use_opengl); - - - - - if(server->use_opengl) - { + if( server->use_opengl && + server->interpolation == AffineEngine::AF_DEFAULT ) { #ifdef HAVE_GL static const char *affine_frag = "uniform sampler2D tex;\n" @@ -550,14 +494,11 @@ void AffineUnit::process_package(LoadPackage *package) unsigned int frag_shader = VFrame::make_shader(0, affine_frag, 0); - if(frag_shader > 0) - { + if( frag_shader > 0 ) { glUseProgram(frag_shader); glUniform1i(glGetUniformLocation(frag_shader, "tex"), 0); glUniformMatrix3fv(glGetUniformLocation(frag_shader, "affine_matrix"), - 1, - 0, - affine_matrix); + 1, 0, affine_matrix); glUniform2f(glGetUniformLocation(frag_shader, "texture_extents"), (GLfloat)server->output->get_texture_w(), (GLfloat)server->output->get_texture_h()); @@ -565,21 +506,19 @@ void AffineUnit::process_package(LoadPackage *package) (GLfloat)server->output->get_w() / server->output->get_texture_w(), (GLfloat)server->output->get_h() / server->output->get_texture_h()); float border_color[] = { 0, 0, 0, 0 }; - if(BC_CModels::is_yuv(server->output->get_color_model())) - { + if(BC_CModels::is_yuv(server->output->get_color_model())) { border_color[1] = 0.5; border_color[2] = 0.5; } - if(!BC_CModels::has_alpha(server->output->get_color_model())) - { + if(!BC_CModels::has_alpha(server->output->get_color_model())) { border_color[3] = 1.0; } glUniform4fv(glGetUniformLocation(frag_shader, "border_color"), - 1, - (GLfloat*)border_color); + 1, (GLfloat*)border_color); server->output->init_screen(); server->output->bind_texture(0); + glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); @@ -591,527 +530,282 @@ void AffineUnit::process_package(LoadPackage *package) #endif // HAVE_GL } - - - - - #define ROUND(x) ((int)((x > 0) ? (x) + 0.5 : (x) - 0.5)) #define MIN4(a,b,c,d) MIN(MIN(MIN(a,b),c),d) #define MAX4(a,b,c,d) MAX(MAX(MAX(a,b),c),d) - tx1 = ROUND(MIN4(dx1 - pivot_offset_x, dx2 - pivot_offset_x, dx3 - pivot_offset_x, dx4 - pivot_offset_x)); - ty1 = ROUND(MIN4(dy1 - pivot_offset_y, dy2 - pivot_offset_y, dy3 - pivot_offset_y, dy4 - pivot_offset_y)); + tx1 = ROUND(MIN4(dx1 - pivot_offset_x, dx2 - pivot_offset_x, dx3 - pivot_offset_x, dx4 - pivot_offset_x)); + ty1 = ROUND(MIN4(dy1 - pivot_offset_y, dy2 - pivot_offset_y, dy3 - pivot_offset_y, dy4 - pivot_offset_y)); - tx2 = ROUND(MAX4(dx1 - pivot_offset_x, dx2 - pivot_offset_x, dx3 - pivot_offset_x, dx4 - pivot_offset_x)); - ty2 = ROUND(MAX4(dy1 - pivot_offset_y, dy2 - pivot_offset_y, dy3 - pivot_offset_y, dy4 - pivot_offset_y)); + tx2 = ROUND(MAX4(dx1 - pivot_offset_x, dx2 - pivot_offset_x, dx3 - pivot_offset_x, dx4 - pivot_offset_x)); + ty2 = ROUND(MAX4(dy1 - pivot_offset_y, dy2 - pivot_offset_y, dy3 - pivot_offset_y, dy4 - pivot_offset_y)); - CLAMP(ty1, pkg->y1, pkg->y2); - CLAMP(ty2, pkg->y1, pkg->y2); - CLAMP(tx1, server->out_x, server->out_x + server->out_w); - CLAMP(tx2, server->out_x, server->out_x + server->out_w); + CLAMP(ty1, pkg->y1, pkg->y2); + CLAMP(ty2, pkg->y1, pkg->y2); + CLAMP(tx1, server->out_x, server->out_x + server->out_w); + CLAMP(tx2, server->out_x, server->out_x + server->out_w); - xinc = m.values[0][0]; - yinc = m.values[1][0]; - winc = m.values[2][0]; + xinc = m.values[0][0]; + yinc = m.values[1][0]; + winc = m.values[2][0]; -//printf("AffineUnit::process_package 2 tx1=%d ty1=%d tx2=%d ty2=%d %f %f\n", tx1, ty1, tx2, ty2, out_x4, out_y4); +//printf("AffineUnit::process_package 2 tx1=%d ty1=%d tx2=%d ty2=%d %f %f\n", +// tx1, ty1, tx2, ty2, out_x4, out_y4); //printf("AffineUnit::process_package %d %d %d %d %d\n", -//__LINE__, -//min_in_x, -//max_in_x, -//min_in_y, -//max_in_y); - -#define CUBIC_ROW(in_row, chroma_offset) \ - transform_cubic(dx, \ - in_row[col1_offset] - chroma_offset, \ - in_row[col2_offset] - chroma_offset, \ - in_row[col3_offset] - chroma_offset, \ - in_row[col4_offset] - chroma_offset) - - -#define TRANSFORM(components, type, temp_type, chroma_offset, max) \ -{ \ - type **in_rows = (type**)server->input->get_rows(); \ - float round_factor = 0.0; \ - if(sizeof(type) < 4) round_factor = 0.5; \ - for(int y = ty1; y < ty2; y++) \ - { \ - type *out_row = (type*)server->output->get_rows()[y]; \ +// __LINE__, min_in_x, max_in_x, min_in_y, max_in_y); + +#define CUBIC_ROW(in_row, chroma_offset) ( !in_row ? 0 : transform_cubic(dx, \ + cp>=min_in_x && cp=min_in_x && c0=min_in_x && c1=min_in_x && c2input->get_rows(); \ + type **out_rows = (type**)server->output->get_rows(); \ + float round_factor = sizeof(type) < 4 ? 0.5 : 0; \ + int comps = components; \ + for( int y=ty1; y max_out_x ) x2 = max_out_x; \ + tx = xinc * x1 + m.values[0][1] * (y + pivot_offset_y) + m.values[0][2] \ + + pivot_offset_x * xinc; \ + ty = yinc * x1 + m.values[1][1] * (y + pivot_offset_y) + m.values[1][2] \ + + pivot_offset_x * yinc; \ + tw = winc * x1 + m.values[2][1] * (y + pivot_offset_y) + m.values[2][2] \ + + pivot_offset_x * winc; \ + type *out = out_row + x1 * comps; \ + for( int x=x1; x= min_out_x && \ - x < max_out_x) \ - { \ - if(itx >= min_in_x && \ - itx <= max_in_x && \ - ity >= min_in_y && \ - ity <= max_in_y) \ - { \ - type *src = in_rows[ity] + itx * components; \ - *out_row++ = *src++; \ - *out_row++ = *src++; \ - *out_row++ = *src++; \ - if(components == 4) *out_row++ = *src; \ - } \ - else \ -/* Fill with chroma */ \ - { \ - *out_row++ = 0; \ - *out_row++ = chroma_offset; \ - *out_row++ = chroma_offset; \ - if(components == 4) *out_row++ = 0; \ - } \ - } \ - else \ -/* Bicubic algorithm */ \ - if(interpolate && \ - x >= min_out_x && \ - x < max_out_x) \ - { \ -/* clipping region */ \ - if ((itx + 2) >= min_in_x && \ - (itx - 1) <= max_in_x && \ - (ity + 2) >= min_in_y && \ - (ity - 1) <= max_in_y) \ - { \ - float dx, dy; \ - \ + if( tw == 0.0 ) { ttx = 0.0; tty = 0.0; } \ + else { ttx = tx / tw; tty = ty / tw; } \ + itx = (int)ttx; ity = (int)tty; \ /* the fractional error */ \ - dx = ttx - itx; \ - dy = tty - ity; \ - \ -/* Row and column offsets in cubic block */ \ - int col1 = itx - 1; \ - int col2 = itx; \ - int col3 = itx + 1; \ - int col4 = itx + 2; \ - CLAMP(col1, min_in_x, max_in_x); \ - CLAMP(col2, min_in_x, max_in_x); \ - CLAMP(col3, min_in_x, max_in_x); \ - CLAMP(col4, min_in_x, max_in_x); \ - int col1_offset = col1 * components; \ - int col2_offset = col2 * components; \ - int col3_offset = col3 * components; \ - int col4_offset = col4 * components; \ + float dx = ttx - itx, dy = tty - ity; \ + if( dx < 0 ) dx += 1; \ + if( dy < 0 ) dy += 1; \ +/* row/col index */ \ + int cp = itx-1, c0 = itx+0, c1 = itx+1, c2 = itx+2; \ + int rp = ity-1, r0 = ity+0, r1 = ity+1, r2 = ity+2; \ + type *rpp, *r0p, *r1p, *r2p; \ + rpp = rp>=min_in_y && rp=min_in_y && r0=min_in_y && r1=min_in_y && r2=min_in_x && c0=min_in_x && c1input->get_rows(); \ + type **out_rows = (type**)server->output->get_rows(); \ + int comps = components; \ + float round_factor = sizeof(type) < 4 ? 0.5 : 0; \ + for( int y=ty1; y max_out_x ) x2 = max_out_x; \ + tx = xinc * x1 + m.values[0][1] * (y + pivot_offset_y) + m.values[0][2] \ + + pivot_offset_x * xinc; \ + ty = yinc * x1 + m.values[1][1] * (y + pivot_offset_y) + m.values[1][2] \ + + pivot_offset_x * yinc; \ + tw = winc * x1 + m.values[2][1] * (y + pivot_offset_y) + m.values[2][2] \ + + pivot_offset_x * winc; \ + type *out = out_row + x1 * comps; \ + for( int x=x1; x=min_in_y && r0=min_in_y && r1input->get_rows(); \ + type **out_rows = (type**)server->output->get_rows(); \ + for( int y=ty1; y max_out_x ) x2 = max_out_x; \ + tx = xinc * x1 + m.values[0][1] * (y + pivot_offset_y) + m.values[0][2] \ + + pivot_offset_x * xinc; \ + ty = yinc * x1 + m.values[1][1] * (y + pivot_offset_y) + m.values[1][2] \ + + pivot_offset_x * yinc; \ + tw = winc * x1 + m.values[2][1] * (y + pivot_offset_y) + m.values[2][2] \ + + pivot_offset_x * winc; \ + type *out = out_row + x1 * components; \ + for( int x=x1; x=min_in_y && ity=min_in_x && itx=min_in_x && itx=min_in_x && itx=min_in_x && itxinput->get_color_model()) - { - case BC_RGB_FLOAT: - TRANSFORM(3, float, float, 0x0, 1.0) - break; - case BC_RGB888: - TRANSFORM(3, unsigned char, int, 0x0, 0xff) - break; - case BC_RGBA_FLOAT: - TRANSFORM(4, float, float, 0x0, 1.0) - break; - case BC_RGBA8888: - TRANSFORM(4, unsigned char, int, 0x0, 0xff) - break; - case BC_YUV888: -// DEBUG -// TRANSFORM(3, unsigned char, int, 0x80, 0xff) -{ - unsigned char **in_rows = (unsigned char**)server->input->get_rows(); - float round_factor = 0.0; - if(sizeof(unsigned char) < 4) round_factor = 0.5; - - for(int y = ty1; y < ty2; y++) - { -//printf("AffineUnit::process_package %d y=%d tx1=%d tx2=%d ty1=%d ty2=%d\n", -//__LINE__, y, tx1, tx2, ty1, ty2); - unsigned char *out_row = (unsigned char*)server->output->get_rows()[y]; - - if(!interpolate) - { - tx = xinc * (tx1 + 0.5) + - m.values[0][1] * (y + pivot_offset_y + 0.5) + - m.values[0][2] + - pivot_offset_x * xinc; - ty = yinc * (tx1 + 0.5) + - m.values[1][1] * (y + pivot_offset_y + 0.5) + - m.values[1][2] + - pivot_offset_x * yinc; - tw = winc * (tx1 + 0.5) + - m.values[2][1] * (y + pivot_offset_y + 0.5) + - m.values[2][2] + - pivot_offset_x * winc; - } - else - { - tx = xinc * tx1 + - m.values[0][1] * (y + pivot_offset_y) + - m.values[0][2] + - pivot_offset_x * xinc; - ty = yinc * tx1 + - m.values[1][1] * (y + pivot_offset_y) + - m.values[1][2] + - pivot_offset_x * yinc; - tw = winc * tx1 + - m.values[2][1] * (y + pivot_offset_y) + - m.values[2][2] + - pivot_offset_x * winc; - } - - - out_row += tx1 * 3; - for(int x = tx1; x < tx2; x++) - { -/* Normalize homogeneous coords */ - if(tw == 0.0) - { - ttx = 0.0; - tty = 0.0; + switch( server->interpolation ) { + case AffineEngine::AF_NEAREST: + switch( server->input->get_color_model() ) { + DO_NEAREST( BC_RGB_FLOAT, 3, float, float, 0x0, 1.0); + DO_NEAREST( BC_RGB888, 3, unsigned char, int, 0x0, 0xff); + DO_NEAREST( BC_RGBA_FLOAT, 4, float, float, 0x0, 1.0); + DO_NEAREST( BC_RGBA8888, 4, unsigned char, int, 0x0, 0xff); + DO_NEAREST( BC_YUV888, 3, unsigned char, int, 0x80, 0xff); + DO_NEAREST( BC_YUVA8888, 4, unsigned char, int, 0x80, 0xff); + DO_NEAREST( BC_RGB161616, 3, uint16_t, int, 0x0, 0xffff); + DO_NEAREST( BC_RGBA16161616, 4, uint16_t, int, 0x0, 0xffff); + DO_NEAREST( BC_YUV161616, 3, uint16_t, int, 0x8000, 0xffff); + DO_NEAREST( BC_YUVA16161616, 4, uint16_t, int, 0x8000, 0xffff); } - else - if(tw != 1.0) - { - ttx = tx / tw; - tty = ty / tw; + break; + case AffineEngine::AF_LINEAR: + switch( server->input->get_color_model() ) { + DO_LINEAR( BC_RGB_FLOAT, 3, float, float, 0x0, 1.0); + DO_LINEAR( BC_RGB888, 3, unsigned char, int, 0x0, 0xff); + DO_LINEAR( BC_RGBA_FLOAT, 4, float, float, 0x0, 1.0); + DO_LINEAR( BC_RGBA8888, 4, unsigned char, int, 0x0, 0xff); + DO_LINEAR( BC_YUV888, 3, unsigned char, int, 0x80, 0xff); + DO_LINEAR( BC_YUVA8888, 4, unsigned char, int, 0x80, 0xff); + DO_LINEAR( BC_RGB161616, 3, uint16_t, int, 0x0, 0xffff); + DO_LINEAR( BC_RGBA16161616, 4, uint16_t, int, 0x0, 0xffff); + DO_LINEAR( BC_YUV161616, 3, uint16_t, int, 0x8000, 0xffff); + DO_LINEAR( BC_YUVA16161616, 4, uint16_t, int, 0x8000, 0xffff); } - else - { - ttx = tx; - tty = ty; + break; + default: + case AffineEngine::AF_CUBIC: + switch( server->input->get_color_model() ) { + DO_CUBIC( BC_RGB_FLOAT, 3, float, float, 0x0, 1.0); + DO_CUBIC( BC_RGB888, 3, unsigned char, int, 0x0, 0xff); + DO_CUBIC( BC_RGBA_FLOAT, 4, float, float, 0x0, 1.0); + DO_CUBIC( BC_RGBA8888, 4, unsigned char, int, 0x0, 0xff); + DO_CUBIC( BC_YUV888, 3, unsigned char, int, 0x80, 0xff); + DO_CUBIC( BC_YUVA8888, 4, unsigned char, int, 0x80, 0xff); + DO_CUBIC( BC_RGB161616, 3, uint16_t, int, 0x0, 0xffff); + DO_CUBIC( BC_RGBA16161616, 4, uint16_t, int, 0x0, 0xffff); + DO_CUBIC( BC_YUV161616, 3, uint16_t, int, 0x8000, 0xffff); + DO_CUBIC( BC_YUVA16161616, 4, uint16_t, int, 0x8000, 0xffff); } - itx = (int)ttx; - ity = (int)tty; - - int row1 = ity - 1; - int row2 = ity; - int row3 = ity + 1; - int row4 = ity + 2; - CLAMP(row1, min_in_y, max_in_y); - CLAMP(row2, min_in_y, max_in_y); - CLAMP(row3, min_in_y, max_in_y); - CLAMP(row4, min_in_y, max_in_y); - -/* Set destination pixels if in clipping region */ - if(!interpolate && - x >= min_out_x && - x < max_out_x) - { - if(itx >= min_in_x && - itx <= max_in_x && - ity >= min_in_y && - ity <= max_in_y) - { - unsigned char *src = in_rows[ity] + itx * 3; - *out_row++ = *src++; - *out_row++ = *src++; - *out_row++ = *src++; - if(3 == 4) *out_row++ = *src; - } - else -/* Fill with chroma */ - { - *out_row++ = 0; - *out_row++ = 0x80; - *out_row++ = 0x80; - if(3 == 4) *out_row++ = 0; - } - } - else -/* Bicubic algorithm */ - if(interpolate && - x >= min_out_x && - x < max_out_x) - { -/* clipping region */ - if ((itx + 2) >= min_in_x && - (itx - 1) <= max_in_x && - (ity + 2) >= min_in_y && - (ity - 1) <= max_in_y) - { - float dx, dy; - -/* the fractional error */ - dx = ttx - itx; - dy = tty - ity; - -/* Row and column offsets in cubic block */ - int col1 = itx - 1; - int col2 = itx; - int col3 = itx + 1; - int col4 = itx + 2; - CLAMP(col1, min_in_x, max_in_x); - CLAMP(col2, min_in_x, max_in_x); - CLAMP(col3, min_in_x, max_in_x); - CLAMP(col4, min_in_x, max_in_x); - int col1_offset = col1 * 3; - int col2_offset = col2 * 3; - int col3_offset = col3 * 3; - int col4_offset = col4 * 3; - - unsigned char *row1_ptr = in_rows[row1]; - unsigned char *row2_ptr = in_rows[row2]; - unsigned char *row3_ptr = in_rows[row3]; - unsigned char *row4_ptr = in_rows[row4]; - int r, g, b, a; - - r = (int)(transform_cubic(dy, - CUBIC_ROW(row1_ptr, 0x0), - CUBIC_ROW(row2_ptr, 0x0), - CUBIC_ROW(row3_ptr, 0x0), - CUBIC_ROW(row4_ptr, 0x0)) + - round_factor); - - row1_ptr++; - row2_ptr++; - row3_ptr++; - row4_ptr++; - g = (int)(transform_cubic(dy, - CUBIC_ROW(row1_ptr, 0x80), - CUBIC_ROW(row2_ptr, 0x80), - CUBIC_ROW(row3_ptr, 0x80), - CUBIC_ROW(row4_ptr, 0x80)) + - round_factor); - g += 0x80; - - row1_ptr++; - row2_ptr++; - row3_ptr++; - row4_ptr++; - b = (int)(transform_cubic(dy, - CUBIC_ROW(row1_ptr, 0x80), - CUBIC_ROW(row2_ptr, 0x80), - CUBIC_ROW(row3_ptr, 0x80), - CUBIC_ROW(row4_ptr, 0x80)) + - round_factor); - b += 0x80; - - if(3 == 4) - { - row1_ptr++; - row2_ptr++; - row3_ptr++; - row4_ptr++; - a = (int)(transform_cubic(dy, - CUBIC_ROW(row1_ptr, 0x0), - CUBIC_ROW(row2_ptr, 0x0), - CUBIC_ROW(row3_ptr, 0x0), - CUBIC_ROW(row4_ptr, 0x0)) + - round_factor); - } - - if(sizeof(unsigned char) < 4) - { - *out_row++ = CLIP(r, 0, 0xff); - *out_row++ = CLIP(g, 0, 0xff); - *out_row++ = CLIP(b, 0, 0xff); - if(3 == 4) *out_row++ = CLIP(a, 0, 0xff); - } - else - { - *out_row++ = r; - *out_row++ = g; - *out_row++ = b; - if(3 == 4) *out_row++ = a; - } - } - else -/* Fill with chroma */ - { - *out_row++ = 0; - *out_row++ = 0x80; - *out_row++ = 0x80; - if(3 == 4) *out_row++ = 0; - } - } - else - { - out_row += 3; - } - -/* increment the transformed coordinates */ - tx += xinc; - ty += yinc; - tw += winc; + break; } } -} - - break; - case BC_YUVA8888: - TRANSFORM(4, unsigned char, int, 0x80, 0xff) - break; - case BC_RGB161616: - TRANSFORM(3, uint16_t, int, 0x0, 0xffff) - break; - case BC_RGBA16161616: - TRANSFORM(4, uint16_t, int, 0x0, 0xffff) - break; - case BC_YUV161616: - TRANSFORM(3, uint16_t, int, 0x8000, 0xffff) - break; - case BC_YUVA16161616: - TRANSFORM(4, uint16_t, int, 0x8000, 0xffff) - break; - } - - } else { int min_x = server->in_x * AFFINE_OVERSAMPLE; @@ -1140,18 +834,13 @@ void AffineUnit::process_package(LoadPackage *package) float h_f = server->in_h; float w_f = server->in_w; - - - if(server->use_opengl) - { + if(server->use_opengl) { return; } - - // Projection -#define DO_STRETCH(type, components) \ -{ \ +#define DO_STRETCH(tag, type, components) \ +case tag: { \ type **in_rows = (type**)server->input->get_rows(); \ type **out_rows = (type**)server->temp->get_rows(); \ \ @@ -1182,59 +871,26 @@ void AffineUnit::process_package(LoadPackage *package) if(components == 4) dst[3] = src[3]; \ } \ } \ -} - - switch(server->input->get_color_model()) - { - case BC_RGB_FLOAT: - DO_STRETCH(float, 3) - break; - case BC_RGB888: - DO_STRETCH(unsigned char, 3) - break; - case BC_RGBA_FLOAT: - DO_STRETCH(float, 4) - break; - case BC_RGBA8888: - DO_STRETCH(unsigned char, 4) - break; - case BC_YUV888: - DO_STRETCH(unsigned char, 3) - break; - case BC_YUVA8888: - DO_STRETCH(unsigned char, 4) - break; - case BC_RGB161616: - DO_STRETCH(uint16_t, 3) - break; - case BC_RGBA16161616: - DO_STRETCH(uint16_t, 4) - break; - case BC_YUV161616: - DO_STRETCH(uint16_t, 3) - break; - case BC_YUVA16161616: - DO_STRETCH(uint16_t, 4) - break; +} break + + switch( server->input->get_color_model() ) { + DO_STRETCH( BC_RGB_FLOAT, float, 3 ); + DO_STRETCH( BC_RGB888, unsigned char, 3 ); + DO_STRETCH( BC_RGBA_FLOAT, float, 4 ); + DO_STRETCH( BC_RGBA8888, unsigned char, 4 ); + DO_STRETCH( BC_YUV888, unsigned char, 3 ); + DO_STRETCH( BC_YUVA8888, unsigned char, 4 ); + DO_STRETCH( BC_RGB161616, uint16_t, 3 ); + DO_STRETCH( BC_RGBA16161616, uint16_t, 4 ); + DO_STRETCH( BC_YUV161616, uint16_t, 3 ); + DO_STRETCH( BC_YUVA16161616, uint16_t, 4 ); } } - - - - } - - - - -AffineEngine::AffineEngine(int total_clients, - int total_packages) - : LoadServer( -//1, 1 -total_clients, total_packages -) +AffineEngine::AffineEngine(int total_clients, int total_packages) + : LoadServer(total_clients, total_packages) //(1, 1) { user_in_viewport = 0; user_in_pivot = 0; @@ -1245,16 +901,17 @@ total_clients, total_packages out_x = out_y = out_w = out_h = 0; in_pivot_x = in_pivot_y = 0; out_pivot_x = out_pivot_y = 0; + interpolation = AF_DEFAULT; this->total_packages = total_packages; } void AffineEngine::init_packages() { - for(int i = 0; i < get_total_packages(); i++) - { + int y1 = 0, npkgs = get_total_packages(); + for( int i=0; iy1 = out_y + (out_h * i / get_total_packages()); - package->y2 = out_y + (out_h * (i + 1) / get_total_packages()); + int y2 = out_y + (out_h * ++i / npkgs); + package->y1 = y1; package->y2 = y2; y1 = y2; } } @@ -1268,90 +925,54 @@ LoadPackage* AffineEngine::new_package() return new AffinePackage; } -void AffineEngine::process(VFrame *output, - VFrame *input, - VFrame *temp, - int mode, - float x1, - float y1, - float x2, - float y2, - float x3, - float y3, - float x4, - float y4, +void AffineEngine::process(VFrame *output, VFrame *input, VFrame *temp, int mode, + float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, int forward) { // printf("AffineEngine::process %d %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f\n", -// __LINE__, -// x1, -// y1, -// x2, -// y2, -// x3, -// y3, -// x4, -// y4); +// __LINE__, x1, y1, x2, y2, x3, y3, x4, y4); // // printf("AffineEngine::process %d %d %d %d %d\n", -// __LINE__, -// in_x, in_y, in_w, in_h); +// __LINE__, in_x, in_y, in_w, in_h); // // printf("AffineEngine::process %d %d %d %d %d\n", -// __LINE__, -// out_x, out_y, out_w, out_h); +// __LINE__, out_x, out_y, out_w, out_h); // // printf("AffineEngine::process %d %d %d %d %d\n", -// __LINE__, -// in_pivot_x, in_pivot_y, out_pivot_x, out_pivot_y); +// __LINE__, in_pivot_x, in_pivot_y, out_pivot_x, out_pivot_y); // // printf("AffineEngine::process %d %d %d %d %d\n", -// __LINE__, -// user_in_pivot, -// user_out_pivot, -// user_in_viewport, -// user_out_viewport); +// __LINE__, user_in_pivot, user_out_pivot, user_in_viewport, user_out_viewport); this->output = output; this->input = input; this->temp = temp; this->mode = mode; - this->x1 = x1; - this->y1 = y1; - this->x2 = x2; - this->y2 = y2; - this->x3 = x3; - this->y3 = y3; - this->x4 = x4; - this->y4 = y4; + this->x1 = x1; this->y1 = y1; + this->x2 = x2; this->y2 = y2; + this->x3 = x3; this->y3 = y3; + this->x4 = x4; this->y4 = y4; this->forward = forward; - - if(!user_in_viewport) - { - in_x = 0; - in_y = 0; + if(!user_in_viewport) { + in_x = 0; in_y = 0; in_w = input->get_w(); in_h = input->get_h(); } - if(!user_out_viewport) - { - out_x = 0; - out_y = 0; + if(!user_out_viewport) { + out_x = 0; out_y = 0; out_w = output->get_w(); out_h = output->get_h(); } - if(use_opengl) - { + if(use_opengl) { set_package_count(1); process_single(); } - else - { + else { set_package_count(total_packages); process_packages(); } @@ -1370,10 +991,8 @@ void AffineEngine::rotate(VFrame *output, this->mode = ROTATE; this->forward = 1; - if(!user_in_viewport) - { - in_x = 0; - in_y = 0; + if( !user_in_viewport ) { + in_x = 0; in_y = 0; in_w = input->get_w(); in_h = input->get_h(); // DEBUG @@ -1384,22 +1003,18 @@ void AffineEngine::rotate(VFrame *output, // printf("AffineEngine::rotate %d %d %d %d %d\n", __LINE__, in_x, in_w, in_y, in_h); } - if(!user_in_pivot) - { + if( !user_in_pivot ) { in_pivot_x = in_x + in_w / 2; in_pivot_y = in_y + in_h / 2; } - if(!user_out_viewport) - { - out_x = 0; - out_y = 0; + if( !user_out_viewport ) { + out_x = 0; out_y = 0; out_w = output->get_w(); out_h = output->get_h(); } - if(!user_out_pivot) - { + if( !user_out_pivot ) { out_pivot_x = out_x + out_w / 2; out_pivot_y = out_y + out_h / 2; } @@ -1429,34 +1044,23 @@ void AffineEngine::rotate(VFrame *output, // // printf(" angle1=%f angle2=%f angle3=%f angle4=%f\n", -// angle1 * 360 / 2 / M_PI, -// angle2 * 360 / 2 / M_PI, -// angle3 * 360 / 2 / M_PI, -// angle4 * 360 / 2 / M_PI); +// angle1 * 360 / 2 / M_PI, angle2 * 360 / 2 / M_PI, +// angle3 * 360 / 2 / M_PI, angle4 * 360 / 2 / M_PI); // // printf(" radius1=%f radius2=%f radius3=%f radius4=%f\n", -// radius1, -// radius2, -// radius3, -// radius4); +// radius1, radius2, radius3, radius4); // // printf(" x1=%f y1=%f x2=%f y2=%f x3=%f y3=%f x4=%f y4=%f\n", -// x1 * w / 100, -// y1 * h / 100, -// x2 * w / 100, -// y2 * h / 100, -// x3 * w / 100, -// y3 * h / 100, -// x4 * w / 100, -// y4 * h / 100); - - if(use_opengl) - { +// x1 * w / 100, y1 * h / 100, +// x2 * w / 100, y2 * h / 100, +// x3 * w / 100, y3 * h / 100, +// x4 * w / 100, y4 * h / 100); + + if(use_opengl) { set_package_count(1); process_single(); } - else - { + else { set_package_count(total_packages); process_packages(); } @@ -1464,10 +1068,8 @@ void AffineEngine::rotate(VFrame *output, void AffineEngine::set_matrix(AffineMatrix *matrix) { - for(int i = 0; i < 3; i++) - { - for(int j = 0; j < 3; j++) - { + for( int i=0; i<3; ++i ) { + for( int j=0; j<3; ++j ) { this->matrix.values[i][j] = matrix->values[i][j]; } } @@ -1475,19 +1077,15 @@ void AffineEngine::set_matrix(AffineMatrix *matrix) void AffineEngine::set_in_viewport(int x, int y, int w, int h) { - this->in_x = x; - this->in_y = y; - this->in_w = w; - this->in_h = h; + this->in_x = x; this->in_y = y; + this->in_w = w; this->in_h = h; this->user_in_viewport = 1; } void AffineEngine::set_out_viewport(int x, int y, int w, int h) { - this->out_x = x; - this->out_y = y; - this->out_w = w; - this->out_h = h; + this->out_x = x; this->out_y = y; + this->out_w = w; this->out_h = h; this->user_out_viewport = 1; } @@ -1535,3 +1133,7 @@ void AffineEngine::unset_viewport() } +void AffineEngine::set_interpolation(int type) +{ + interpolation = type; +} diff --git a/cinelerra-5.1/cinelerra/affine.h b/cinelerra-5.1/cinelerra/affine.h index d03f6cd8..339c8cbb 100644 --- a/cinelerra-5.1/cinelerra/affine.h +++ b/cinelerra-5.1/cinelerra/affine.h @@ -86,24 +86,13 @@ public: // Range of coords is 0 to 100 for coordinates in the image. // The coordinate locations are clockwise around the image. - void process(VFrame *output, - VFrame *input, - VFrame *temp, - int mode, - float x1, - float y1, - float x2, - float y2, - float x3, - float y3, - float x4, - float y4, + void process(VFrame *output, VFrame *input, VFrame *temp, int mode, + float x1, float y1, float x2, float y2, + float x3, float y3, float x4, float y4, int forward); // Do rotation with the affine/perspective transform. // This removes some of the extremely faint artifacts in the trig rotation. - void rotate(VFrame *output, - VFrame *input, - float angle); + void rotate(VFrame *output, VFrame *input, float angle); void set_matrix(AffineMatrix *matrix); // Set the viewport to transform. The transform is based on the input viewport. // The output viewport clips the transformed output. @@ -127,6 +116,8 @@ public: // Never used void unset_pivot(); void unset_viewport(); +// default: AF_CUBIC + void set_interpolation(int type); // To use OpenGL for the processing, set to 1 void set_opengl(int value); void init_packages(); @@ -136,8 +127,7 @@ public: VFrame *input, *output, *temp; int mode; - enum - { + enum { PERSPECTIVE, SHEER, STRETCH, @@ -145,6 +135,14 @@ public: // multiply directly by a matrix. TRANSFORM }; + int interpolation; + enum { + AF_DEFAULT, + AF_NEAREST, + AF_LINEAR, + AF_CUBIC, + AF_MODES + }; // arbitrary matrix AffineMatrix matrix; diff --git a/cinelerra-5.1/cinelerra/assetedit.C b/cinelerra-5.1/cinelerra/assetedit.C index 3eee273f..83833513 100644 --- a/cinelerra-5.1/cinelerra/assetedit.C +++ b/cinelerra-5.1/cinelerra/assetedit.C @@ -78,11 +78,7 @@ AssetEdit::~AssetEdit() void AssetEdit::edit_asset(Indexable *indexable) { - if(this->indexable) - { - close_window(); - } - + close_window(); this->indexable = indexable; this->indexable->add_user(); diff --git a/cinelerra-5.1/cinelerra/assetpopup.C b/cinelerra-5.1/cinelerra/assetpopup.C index 12a51429..f85b05c0 100644 --- a/cinelerra-5.1/cinelerra/assetpopup.C +++ b/cinelerra-5.1/cinelerra/assetpopup.C @@ -147,17 +147,8 @@ int AssetPopupInfo::handle_event() { if(mwindow->session->drag_assets->total) { - if(mwindow->awindow->asset_edit->running() && - mwindow->awindow->asset_edit->window) - { - mwindow->awindow->asset_edit->window->raise_window(); - mwindow->awindow->asset_edit->window->flush(); - } - else - { - mwindow->awindow->asset_edit->edit_asset( - mwindow->session->drag_assets->values[0]); - } + mwindow->awindow->asset_edit->edit_asset( + mwindow->session->drag_assets->values[0]); } else if(mwindow->session->drag_clips->total) diff --git a/cinelerra-5.1/cinelerra/clipedit.C b/cinelerra-5.1/cinelerra/clipedit.C index 3e956e74..e3065673 100644 --- a/cinelerra-5.1/cinelerra/clipedit.C +++ b/cinelerra-5.1/cinelerra/clipedit.C @@ -127,6 +127,7 @@ BC_Window* ClipEdit::new_gui() void ClipEdit::edit_clip(EDL *clip) { + close_window(); // Allow more than one window so we don't have to delete the clip in handle_event if(!this->clip) { diff --git a/cinelerra-5.1/plugins/perspective/perspective.C b/cinelerra-5.1/plugins/perspective/perspective.C index e270bc8c..6e2c7f97 100644 --- a/cinelerra-5.1/plugins/perspective/perspective.C +++ b/cinelerra-5.1/plugins/perspective/perspective.C @@ -36,15 +36,12 @@ REGISTER_PLUGIN(PerspectiveMain) PerspectiveConfig::PerspectiveConfig() { - x1 = 0; - y1 = 0; - x2 = 100; - y2 = 0; - x3 = 100; - y3 = 100; - x4 = 0; - y4 = 100; + x1 = 0; y1 = 0; + x2 = 100; y2 = 0; + x3 = 100; y3 = 100; + x4 = 0; y4 = 100; mode = AffineEngine::PERSPECTIVE; + smoothing = AffineEngine::AF_DEFAULT; window_w = 400; window_h = 450; current_point = 0; @@ -63,31 +60,26 @@ int PerspectiveConfig::equivalent(PerspectiveConfig &that) EQUIV(x4, that.x4) && EQUIV(y4, that.y4) && mode == that.mode && + smoothing == that.smoothing && forward == that.forward; } void PerspectiveConfig::copy_from(PerspectiveConfig &that) { - x1 = that.x1; - y1 = that.y1; - x2 = that.x2; - y2 = that.y2; - x3 = that.x3; - y3 = that.y3; - x4 = that.x4; - y4 = that.y4; + x1 = that.x1; y1 = that.y1; + x2 = that.x2; y2 = that.y2; + x3 = that.x3; y3 = that.y3; + x4 = that.x4; y4 = that.y4; mode = that.mode; + smoothing = that.smoothing; window_w = that.window_w; window_h = that.window_h; current_point = that.current_point; forward = that.forward; } -void PerspectiveConfig::interpolate(PerspectiveConfig &prev, - PerspectiveConfig &next, - int64_t prev_frame, - int64_t next_frame, - int64_t current_frame) +void PerspectiveConfig::interpolate(PerspectiveConfig &prev, PerspectiveConfig &next, + int64_t prev_frame, int64_t next_frame, int64_t current_frame) { double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame); double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame); @@ -100,28 +92,15 @@ void PerspectiveConfig::interpolate(PerspectiveConfig &prev, this->x4 = prev.x4 * prev_scale + next.x4 * next_scale; this->y4 = prev.y4 * prev_scale + next.y4 * next_scale; mode = prev.mode; + smoothing = prev.smoothing; forward = prev.forward; } - - - - - - - - - - - PerspectiveWindow::PerspectiveWindow(PerspectiveMain *plugin) : PluginClientWindow(plugin, - plugin->config.window_w, - plugin->config.window_h, - plugin->config.window_w, - plugin->config.window_h, - 0) + plugin->config.window_w, plugin->config.window_h, + plugin->config.window_w, plugin->config.window_h, 0) { //printf("PerspectiveWindow::PerspectiveWindow 1 %d %d\n", plugin->config.window_w, plugin->config.window_h); this->plugin = plugin; @@ -136,69 +115,43 @@ void PerspectiveWindow::create_objects() int x = 10, y = 10; add_subwindow(canvas = new PerspectiveCanvas(plugin, - x, - y, - get_w() - 20, - get_h() - 140)); + x, y, get_w() - 20, get_h() - 140)); canvas->set_cursor(CROSS_CURSOR, 0, 0); y += canvas->get_h() + 10; add_subwindow(new BC_Title(x, y, _("Current X:"))); x += 80; this->x = new PerspectiveCoord(this, - plugin, - x, - y, - plugin->get_current_x(), - 1); + plugin, x, y, plugin->get_current_x(), 1); this->x->create_objects(); x += 140; add_subwindow(new BC_Title(x, y, _("Y:"))); x += 20; this->y = new PerspectiveCoord(this, - plugin, - x, - y, - plugin->get_current_y(), - 0); + plugin, x, y, plugin->get_current_y(), 0); this->y->create_objects(); - y += 30; - x = 10; - add_subwindow(new PerspectiveReset(plugin, x, y)); - x += 100; + x = 10; y += 30; add_subwindow(mode_perspective = new PerspectiveMode(plugin, - x, - y, - AffineEngine::PERSPECTIVE, - _("Perspective"))); + x, y, AffineEngine::PERSPECTIVE, _("Perspective"))); x += 120; add_subwindow(mode_sheer = new PerspectiveMode(plugin, - x, - y, - AffineEngine::SHEER, - _("Sheer"))); - x = 110; - y += 30; + x, y, AffineEngine::SHEER, _("Sheer"))); + x += 100; + add_subwindow(affine = new PerspectiveAffine(this, x, y)); + affine->create_objects(); + x = 10; y += 30; add_subwindow(mode_stretch = new PerspectiveMode(plugin, - x, - y, - AffineEngine::STRETCH, - _("Stretch"))); + x, y, AffineEngine::STRETCH, _("Stretch"))); + x += 120; + add_subwindow(new PerspectiveReset(plugin, x, y)); update_canvas(); - y += 30; - x = 10; + x = 10; y += 30; add_subwindow(new BC_Title(x, y, _("Perspective direction:"))); x += 170; add_subwindow(forward = new PerspectiveDirection(plugin, - x, - y, - 1, - _("Forward"))); + x, y, 1, _("Forward"))); x += 100; add_subwindow(reverse = new PerspectiveDirection(plugin, - x, - y, - 0, - _("Reverse"))); + x, y, 0, _("Reverse"))); show_window(); } @@ -216,29 +169,19 @@ void PerspectiveWindow::update_canvas() int x1, y1, x2, y2, x3, y3, x4, y4; calculate_canvas_coords(x1, y1, x2, y2, x3, y3, x4, y4); -// printf("PerspectiveWindow::update_canvas %d,%d %d,%d %d,%d %d,%d\n", -// x1, -// y1, -// x2, -// y2, -// x3, -// y3, -// x4, -// y4); +//printf("PerspectiveWindow::update_canvas %d,%d %d,%d %d,%d %d,%d\n", +// x1, y1, x2, y2, x3, y3, x4, y4); // Draw divisions canvas->set_color(WHITE); #define DIVISIONS 10 - for(int i = 0; i <= DIVISIONS; i++) - { -// latitude - canvas->draw_line( + for( int i=0; i<=DIVISIONS; ++i ) { + canvas->draw_line( // latitude x1 + (x4 - x1) * i / DIVISIONS, y1 + (y4 - y1) * i / DIVISIONS, x2 + (x3 - x2) * i / DIVISIONS, y2 + (y3 - y2) * i / DIVISIONS); -// longitude - canvas->draw_line( + canvas->draw_line( // longitude x1 + (x2 - x1) * i / DIVISIONS, y1 + (y2 - y1) * i / DIVISIONS, x4 + (x3 - x4) * i / DIVISIONS, @@ -285,20 +228,14 @@ void PerspectiveWindow::update_coord() y->update(plugin->get_current_y()); } -void PerspectiveWindow::calculate_canvas_coords(int &x1, - int &y1, - int &x2, - int &y2, - int &x3, - int &y3, - int &x4, - int &y4) +void PerspectiveWindow::calculate_canvas_coords( + int &x1, int &y1, int &x2, int &y2, + int &x3, int &y3, int &x4, int &y4) { int w = canvas->get_w() - 1; int h = canvas->get_h() - 1; - if(plugin->config.mode == AffineEngine::PERSPECTIVE || - plugin->config.mode == AffineEngine::STRETCH) - { + if( plugin->config.mode == AffineEngine::PERSPECTIVE || + plugin->config.mode == AffineEngine::STRETCH ) { x1 = (int)(plugin->config.x1 * w / 100); y1 = (int)(plugin->config.y1 * h / 100); x2 = (int)(plugin->config.x2 * w / 100); @@ -308,8 +245,7 @@ void PerspectiveWindow::calculate_canvas_coords(int &x1, x4 = (int)(plugin->config.x4 * w / 100); y4 = (int)(plugin->config.y4 * h / 100); } - else - { + else { x1 = (int)(plugin->config.x1 * w) / 100; y1 = 0; x2 = x1 + w; @@ -322,13 +258,8 @@ void PerspectiveWindow::calculate_canvas_coords(int &x1, } - - PerspectiveCanvas::PerspectiveCanvas(PerspectiveMain *plugin, - int x, - int y, - int w, - int h) + int x, int y, int w, int h) : BC_SubWindow(x, y, w, h, BLACK) { this->plugin = plugin; @@ -336,12 +267,9 @@ PerspectiveCanvas::PerspectiveCanvas(PerspectiveMain *plugin, } - - int PerspectiveCanvas::button_press_event() { - if(is_event_win() && cursor_inside()) - { + if( is_event_win() && cursor_inside() ) { // Set current point int x1, y1, x2, y2, x3, y3, x4, y4; int cursor_x = get_cursor_x(); @@ -360,40 +288,32 @@ int PerspectiveCanvas::button_press_event() // y3); float min = distance1; plugin->config.current_point = 0; - if(distance2 < min) - { + if( distance2 < min ) { min = distance2; plugin->config.current_point = 1; } - if(distance3 < min) - { + if( distance3 < min ) { min = distance3; plugin->config.current_point = 2; } - if(distance4 < min) - { + if( distance4 < min ) { min = distance4; plugin->config.current_point = 3; } - if(plugin->config.mode == AffineEngine::SHEER) - { - if(plugin->config.current_point == 1) + if( plugin->config.mode == AffineEngine::SHEER ) { + if( plugin->config.current_point == 1 ) plugin->config.current_point = 0; - else - if(plugin->config.current_point == 2) + else if( plugin->config.current_point == 2 ) plugin->config.current_point = 3; } start_cursor_x = cursor_x; start_cursor_y = cursor_y; - if(alt_down() || shift_down()) - { - if(alt_down()) - state = PerspectiveCanvas::DRAG_FULL; - else - state = PerspectiveCanvas::ZOOM; - + if( alt_down() || shift_down() ) { + state = alt_down() ? + PerspectiveCanvas::DRAG_FULL : + PerspectiveCanvas::ZOOM; // Get starting positions start_x1 = plugin->config.x1; start_y1 = plugin->config.y1; @@ -404,10 +324,8 @@ int PerspectiveCanvas::button_press_event() start_x4 = plugin->config.x4; start_y4 = plugin->config.y4; } - else - { + else { state = PerspectiveCanvas::DRAG; - // Get starting positions start_x1 = plugin->get_current_x(); start_y1 = plugin->get_current_y(); @@ -422,8 +340,7 @@ int PerspectiveCanvas::button_press_event() int PerspectiveCanvas::button_release_event() { - if(state != PerspectiveCanvas::NONE) - { + if( state != PerspectiveCanvas::NONE ) { state = PerspectiveCanvas::NONE; return 1; } @@ -432,18 +349,14 @@ int PerspectiveCanvas::button_release_event() int PerspectiveCanvas::cursor_motion_event() { - if(state != PerspectiveCanvas::NONE) - { + if( state != PerspectiveCanvas::NONE ) { int w = get_w() - 1; int h = get_h() - 1; - if(state == PerspectiveCanvas::DRAG) - { + if( state == PerspectiveCanvas::DRAG ) { plugin->set_current_x((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x1); plugin->set_current_y((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y1); } - else - if(state == PerspectiveCanvas::DRAG_FULL) - { + else if( state == PerspectiveCanvas::DRAG_FULL ) { plugin->config.x1 = ((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x1); plugin->config.y1 = ((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y1); plugin->config.x2 = ((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x2); @@ -453,17 +366,9 @@ int PerspectiveCanvas::cursor_motion_event() plugin->config.x4 = ((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x4); plugin->config.y4 = ((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y4); } - else - if(state == PerspectiveCanvas::ZOOM) - { - float center_x = (start_x1 + - start_x2 + - start_x3 + - start_x4) / 4; - float center_y = (start_y1 + - start_y2 + - start_y3 + - start_y4) / 4; + else if( state == PerspectiveCanvas::ZOOM ) { + float center_x = (start_x1 + start_x2 + start_x3 + start_x4) / 4; + float center_y = (start_y1 + start_y2 + start_y3 + start_y4) / 4; float zoom = (float)(get_cursor_y() - start_cursor_y + 640) / 640; plugin->config.x1 = center_x + (start_x1 - center_x) * zoom; plugin->config.y1 = center_y + (start_y1 - center_y) * zoom; @@ -484,16 +389,8 @@ int PerspectiveCanvas::cursor_motion_event() } - - - - PerspectiveCoord::PerspectiveCoord(PerspectiveWindow *gui, - PerspectiveMain *plugin, - int x, - int y, - float value, - int is_x) + PerspectiveMain *plugin, int x, int y, float value, int is_x) : BC_TumbleTextBox(gui, value, (float)-100, (float)200, x, y, 100) { this->plugin = plugin; @@ -502,39 +399,28 @@ PerspectiveCoord::PerspectiveCoord(PerspectiveWindow *gui, int PerspectiveCoord::handle_event() { - if(is_x) - plugin->set_current_x(atof(get_text())); + float v = atof(get_text()); + if( is_x ) + plugin->set_current_x(v); else - plugin->set_current_y(atof(get_text())); + plugin->set_current_y(v); ((PerspectiveWindow*)plugin->thread->window)->update_canvas(); plugin->send_configure_change(); return 1; } - - - - - - -PerspectiveReset::PerspectiveReset(PerspectiveMain *plugin, - int x, - int y) +PerspectiveReset::PerspectiveReset(PerspectiveMain *plugin, int x, int y) : BC_GenericButton(x, y, _("Reset")) { this->plugin = plugin; } int PerspectiveReset::handle_event() { - plugin->config.x1 = 0; - plugin->config.y1 = 0; - plugin->config.x2 = 100; - plugin->config.y2 = 0; - plugin->config.x3 = 100; - plugin->config.y3 = 100; - plugin->config.x4 = 0; - plugin->config.y4 = 100; + plugin->config.x1 = 0; plugin->config.y1 = 0; + plugin->config.x2 = 100; plugin->config.y2 = 0; + plugin->config.x3 = 100; plugin->config.y3 = 100; + plugin->config.x4 = 0; plugin->config.y4 = 100; ((PerspectiveWindow*)plugin->thread->window)->update_canvas(); ((PerspectiveWindow*)plugin->thread->window)->update_coord(); plugin->send_configure_change(); @@ -542,20 +428,8 @@ int PerspectiveReset::handle_event() } - - - - - - - - - PerspectiveMode::PerspectiveMode(PerspectiveMain *plugin, - int x, - int y, - int value, - char *text) + int x, int y, int value, char *text) : BC_Radial(x, y, plugin->config.mode == value, text) { this->plugin = plugin; @@ -571,8 +445,6 @@ int PerspectiveMode::handle_event() } - - PerspectiveDirection::PerspectiveDirection(PerspectiveMain *plugin, int x, int y, @@ -592,15 +464,53 @@ int PerspectiveDirection::handle_event() } +int PerspectiveAffineItem::handle_event() +{ + ((PerspectiveAffine *)get_popup_menu())->update(id); + return 1; +} +PerspectiveAffine::PerspectiveAffine(PerspectiveWindow *gui, int x, int y) + : BC_PopupMenu(x, y, 100, "", 1) +{ + this->gui = gui; + affine_modes[AffineEngine::AF_DEFAULT] = _("default"); + affine_modes[AffineEngine::AF_NEAREST] = _("Nearest"); + affine_modes[AffineEngine::AF_LINEAR] = _("Linear"); + affine_modes[AffineEngine::AF_CUBIC] = _("Cubic"); + mode = -1; +} +PerspectiveAffine::~PerspectiveAffine() +{ + int id = total_items(); + while( --id >= 0 ) + remove_item(get_item(id)); + for( int id=0; idplugin->config.smoothing, 0); +} - - - - - - +void PerspectiveAffine::update(int mode, int send) +{ + if( this->mode == mode ) return; + this->mode = mode; + set_text(affine_modes[mode]); + gui->plugin->config.smoothing = mode; + if( send ) gui->plugin->send_configure_change(); +} PerspectiveMain::PerspectiveMain(PluginServer *server) : PluginVClient(server) @@ -621,27 +531,23 @@ const char* PerspectiveMain::plugin_title() { return _("Perspective"); } int PerspectiveMain::is_realtime() { return 1; } - NEW_WINDOW_MACRO(PerspectiveMain, PerspectiveWindow) LOAD_CONFIGURATION_MACRO(PerspectiveMain, PerspectiveConfig) - - void PerspectiveMain::update_gui() { - if(thread) - { + if( !thread ) return; //printf("PerspectiveMain::update_gui 1\n"); - thread->window->lock_window(); + thread->window->lock_window(); + PerspectiveWindow *gui = (PerspectiveWindow*)thread->window; //printf("PerspectiveMain::update_gui 2\n"); - load_configuration(); - ((PerspectiveWindow*)thread->window)->update_coord(); - ((PerspectiveWindow*)thread->window)->update_mode(); - ((PerspectiveWindow*)thread->window)->update_canvas(); - thread->window->unlock_window(); + load_configuration(); + gui->update_coord(); + gui->update_mode(); + gui->update_canvas(); + thread->window->unlock_window(); //printf("PerspectiveMain::update_gui 3\n"); - } } @@ -666,6 +572,7 @@ void PerspectiveMain::save_data(KeyFrame *keyframe) output.tag.set_property("Y4", config.y4); output.tag.set_property("MODE", config.mode); + output.tag.set_property("SMOOTHING", config.smoothing); output.tag.set_property("FORWARD", config.forward); output.tag.set_property("WINDOW_W", config.window_w); output.tag.set_property("WINDOW_H", config.window_h); @@ -679,320 +586,187 @@ void PerspectiveMain::save_data(KeyFrame *keyframe) void PerspectiveMain::read_data(KeyFrame *keyframe) { FileXML input; - input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data())); - int result = 0; - while(!result) - { - result = input.read_tag(); - - if(!result) - { - if(input.tag.title_is("PERSPECTIVE")) - { - config.x1 = input.tag.get_property("X1", config.x1); - config.x2 = input.tag.get_property("X2", config.x2); - config.x3 = input.tag.get_property("X3", config.x3); - config.x4 = input.tag.get_property("X4", config.x4); - config.y1 = input.tag.get_property("Y1", config.y1); - config.y2 = input.tag.get_property("Y2", config.y2); - config.y3 = input.tag.get_property("Y3", config.y3); - config.y4 = input.tag.get_property("Y4", config.y4); - - config.mode = input.tag.get_property("MODE", config.mode); - config.forward = input.tag.get_property("FORWARD", config.forward); - config.window_w = input.tag.get_property("WINDOW_W", config.window_w); - config.window_h = input.tag.get_property("WINDOW_H", config.window_h); - } + while(!(result = input.read_tag()) ) { + if(input.tag.title_is("PERSPECTIVE")) { + config.x1 = input.tag.get_property("X1", config.x1); + config.x2 = input.tag.get_property("X2", config.x2); + config.x3 = input.tag.get_property("X3", config.x3); + config.x4 = input.tag.get_property("X4", config.x4); + config.y1 = input.tag.get_property("Y1", config.y1); + config.y2 = input.tag.get_property("Y2", config.y2); + config.y3 = input.tag.get_property("Y3", config.y3); + config.y4 = input.tag.get_property("Y4", config.y4); + + config.mode = input.tag.get_property("MODE", config.mode); + config.smoothing = input.tag.get_property("SMOOTHING", config.smoothing); + config.forward = input.tag.get_property("FORWARD", config.forward); + config.window_w = input.tag.get_property("WINDOW_W", config.window_w); + config.window_h = input.tag.get_property("WINDOW_H", config.window_h); } } } float PerspectiveMain::get_current_x() { - switch(config.current_point) - { - case 0: - return config.x1; - break; - case 1: - return config.x2; - break; - case 2: - return config.x3; - break; - case 3: - return config.x4; - break; + switch( config.current_point ) { + case 0: return config.x1; + case 1: return config.x2; + case 2: return config.x3; + case 3: return config.x4; } return 0; } float PerspectiveMain::get_current_y() { - switch(config.current_point) - { - case 0: - return config.y1; - break; - case 1: - return config.y2; - break; - case 2: - return config.y3; - break; - case 3: - return config.y4; - break; + switch( config.current_point ) { + case 0: return config.y1; + case 1: return config.y2; + case 2: return config.y3; + case 3: return config.y4; } return 0; } void PerspectiveMain::set_current_x(float value) { - switch(config.current_point) - { - case 0: - config.x1 = value; - break; - case 1: - config.x2 = value; - break; - case 2: - config.x3 = value; - break; - case 3: - config.x4 = value; - break; + switch( config.current_point ) { + case 0: config.x1 = value; break; + case 1: config.x2 = value; break; + case 2: config.x3 = value; break; + case 3: config.x4 = value; break; } } void PerspectiveMain::set_current_y(float value) { - switch(config.current_point) - { - case 0: - config.y1 = value; - break; - case 1: - config.y2 = value; - break; - case 2: - config.y3 = value; - break; - case 3: - config.y4 = value; - break; + switch( config.current_point ) { + case 0: config.y1 = value; break; + case 1: config.y2 = value; break; + case 2: config.y3 = value; break; + case 3: config.y4 = value; break; } } - - int PerspectiveMain::process_buffer(VFrame *frame, - int64_t start_position, - double frame_rate) + int64_t start_position, double frame_rate) { /*int need_reconfigure =*/ load_configuration(); + int smoothing = config.smoothing; +// default smoothing uses opengl if possible + int use_opengl = smoothing != AffineEngine::AF_DEFAULT ? 0 : +// Opengl does some funny business with stretching. + config.mode == AffineEngine::PERSPECTIVE || + config.mode == AffineEngine::SHEER ? get_use_opengl() : 0; + + read_frame(frame, 0, start_position, frame_rate, use_opengl); // Do nothing + if( EQUIV(config.x1, 0) && EQUIV(config.y1, 0) && - EQUIV(config.x2, 100) && EQUIV(config.y2, 0) && - EQUIV(config.x3, 100) && EQUIV(config.y3, 100) && - EQUIV(config.x4, 0) && EQUIV(config.y4, 100)) - { - read_frame(frame, - 0, - start_position, - frame_rate, - get_use_opengl()); + EQUIV(config.x2, 100) && EQUIV(config.y2, 0) && + EQUIV(config.x3, 100) && EQUIV(config.y3, 100) && + EQUIV(config.x4, 0) && EQUIV(config.y4, 100) ) return 1; + + if( !engine ) { + int cpus = get_project_smp() + 1; + engine = new AffineEngine(cpus, cpus); } + engine->set_interpolation(smoothing); -// Opengl does some funny business with stretching. - int use_opengl = get_use_opengl() && - (config.mode == AffineEngine::PERSPECTIVE || - config.mode == AffineEngine::SHEER); - read_frame(frame, - 0, - start_position, - frame_rate, - use_opengl); - - if(!engine) engine = new AffineEngine(get_project_smp() + 1, - get_project_smp() + 1); - - if(use_opengl) + if( use_opengl ) return run_opengl(); - - this->input = frame; this->output = frame; - int w = frame->get_w(); - int h = frame->get_h(); + int w = frame->get_w(), need_w = w; + int h = frame->get_h(), need_h = h; int color_model = frame->get_color_model(); - - if(temp && - config.mode == AffineEngine::STRETCH && - (temp->get_w() != w * AFFINE_OVERSAMPLE || - temp->get_h() != h * AFFINE_OVERSAMPLE)) - { - delete temp; - temp = 0; - } - else - if(temp && - (config.mode == AffineEngine::PERSPECTIVE || - config.mode == AffineEngine::SHEER) && - (temp->get_w() != w || - temp->get_h() != h)) - { - delete temp; - temp = 0; - } - - if(config.mode == AffineEngine::STRETCH) - { - if(!temp) - { - temp = new VFrame(0, - -1, - w * AFFINE_OVERSAMPLE, - h * AFFINE_OVERSAMPLE, - color_model, - -1); - } - temp->clear_frame(); - } - - if(config.mode == AffineEngine::PERSPECTIVE || - config.mode == AffineEngine::SHEER) - { - if(frame->get_rows()[0] == frame->get_rows()[0]) - { - if(!temp) - { - temp = new VFrame(0, - -1, - w, - h, - color_model, - -1); + switch( config.mode ) { + case AffineEngine::STRETCH: + need_w *= AFFINE_OVERSAMPLE; + need_h *= AFFINE_OVERSAMPLE; + case AffineEngine::SHEER: + case AffineEngine::PERSPECTIVE: + if( temp ) { + if( temp->get_w() != need_w || temp->get_h() != need_h || + temp->get_color_model() != color_model ) { + delete temp; temp = 0; } - temp->copy_from(input); - input = temp; } + if( !temp ) + temp = new VFrame(need_w, need_h, color_model); + break; + } + switch( config.mode ) { + case AffineEngine::STRETCH: + temp->clear_frame(); + break; + case AffineEngine::PERSPECTIVE: + case AffineEngine::SHEER: + temp->copy_from(input); + input = temp; output->clear_frame(); + break; + default: + delete temp; temp = 0; + break; } - - engine->process(output, - input, - temp, - config.mode, - config.x1, - config.y1, - config.x2, - config.y2, - config.x3, - config.y3, - config.x4, - config.y4, + engine->process(output, input, temp, config.mode, + config.x1, config.y1, config.x2, config.y2, + config.x3, config.y3, config.x4, config.y4, config.forward); - - - // Resample - if(config.mode == AffineEngine::STRETCH) - { -#define RESAMPLE(type, components, chroma_offset) \ -{ \ - for(int i = 0; i < h; i++) \ - { \ - type *out_row = (type*)output->get_rows()[i]; \ - type *in_row1 = (type*)temp->get_rows()[i * AFFINE_OVERSAMPLE]; \ - type *in_row2 = (type*)temp->get_rows()[i * AFFINE_OVERSAMPLE + 1]; \ - for(int j = 0; j < w; j++) \ - { \ - out_row[0] = (in_row1[0] + \ - in_row1[components] + \ - in_row2[0] + \ - in_row2[components]) / \ - AFFINE_OVERSAMPLE / \ - AFFINE_OVERSAMPLE; \ - out_row[1] = ((in_row1[1] + \ - in_row1[components + 1] + \ - in_row2[1] + \ - in_row2[components + 1]) - \ - chroma_offset * \ - AFFINE_OVERSAMPLE * \ - AFFINE_OVERSAMPLE) / \ - AFFINE_OVERSAMPLE / \ - AFFINE_OVERSAMPLE + \ - chroma_offset; \ - out_row[2] = ((in_row1[2] + \ - in_row1[components + 2] + \ - in_row2[2] + \ - in_row2[components + 2]) - \ - chroma_offset * \ - AFFINE_OVERSAMPLE * \ - AFFINE_OVERSAMPLE) / \ - AFFINE_OVERSAMPLE / \ - AFFINE_OVERSAMPLE + \ - chroma_offset; \ - if(components == 4) \ - { \ - out_row[3] = (in_row1[3] + \ - in_row1[components + 3] + \ - in_row2[3] + \ - in_row2[components + 3]) / \ - AFFINE_OVERSAMPLE / \ - AFFINE_OVERSAMPLE; \ - } \ - out_row += components; \ - in_row1 += components * AFFINE_OVERSAMPLE; \ - in_row2 += components * AFFINE_OVERSAMPLE; \ - } \ - } \ -} - - switch(frame->get_color_model()) - { - case BC_RGB_FLOAT: - RESAMPLE(float, 3, 0) - break; - case BC_RGB888: - RESAMPLE(unsigned char, 3, 0) - break; - case BC_RGBA_FLOAT: - RESAMPLE(float, 4, 0) - break; - case BC_RGBA8888: - RESAMPLE(unsigned char, 4, 0) - break; - case BC_YUV888: - RESAMPLE(unsigned char, 3, 0x80) - break; - case BC_YUVA8888: - RESAMPLE(unsigned char, 4, 0x80) - break; - case BC_RGB161616: - RESAMPLE(uint16_t, 3, 0) - break; - case BC_RGBA16161616: - RESAMPLE(uint16_t, 4, 0) - break; - case BC_YUV161616: - RESAMPLE(uint16_t, 3, 0x8000) - break; - case BC_YUVA16161616: - RESAMPLE(uint16_t, 4, 0x8000) - break; + if( config.mode == AffineEngine::STRETCH ) { + +#define RESAMPLE(tag, type, components, chroma_offset) \ +case tag: { \ + int os = AFFINE_OVERSAMPLE, os2 = os*os; \ + for( int i=0; iget_rows()[i]; \ + type *in_row1 = (type*)temp->get_rows()[i * os]; \ + type *in_row2 = (type*)temp->get_rows()[i * os + 1]; \ + for( int j=0; jget_color_model() ) { + RESAMPLE( BC_RGB_FLOAT, float, 3, 0 ); + RESAMPLE( BC_RGB888, unsigned char, 3, 0 ); + RESAMPLE( BC_RGBA_FLOAT, float, 4, 0 ); + RESAMPLE( BC_RGBA8888, unsigned char, 4, 0 ); + RESAMPLE( BC_YUV888, unsigned char, 3, 0x80 ); + RESAMPLE( BC_YUVA8888, unsigned char, 4, 0x80 ); + RESAMPLE( BC_RGB161616, uint16_t, 3, 0 ); + RESAMPLE( BC_RGBA16161616, uint16_t, 4, 0 ); + RESAMPLE( BC_YUV161616, uint16_t, 3, 0x8000 ); + RESAMPLE( BC_YUVA16161616, uint16_t, 4, 0x8000 ); } } @@ -1004,26 +778,12 @@ int PerspectiveMain::handle_opengl() { #ifdef HAVE_GL engine->set_opengl(1); - engine->process(get_output(), - get_output(), - get_output(), - config.mode, - config.x1, - config.y1, - config.x2, - config.y2, - config.x3, - config.y3, - config.x4, - config.y4, + engine->process(get_output(), get_output(), get_output(), config.mode, + config.x1, config.y1, config.x2, config.y2, + config.x3, config.y3, config.x4, config.y4, config.forward); engine->set_opengl(0); return 0; #endif } - - - - - diff --git a/cinelerra-5.1/plugins/perspective/perspective.h b/cinelerra-5.1/plugins/perspective/perspective.h index a4643d88..18e54584 100644 --- a/cinelerra-5.1/plugins/perspective/perspective.h +++ b/cinelerra-5.1/plugins/perspective/perspective.h @@ -32,11 +32,17 @@ #include "pluginvclient.h" #include "vframe.h" -class PerspectiveMain; -class PerspectiveWindow; - - +class PerspectiveConfig; +class PerspectiveCanvas; +class PerspectiveCoord; +class PerspectiveReset; +class PerspectiveMode; +class PerspectiveDirection; +class PerspectiveAffine; +class PerspectiveAffineItem; +class PerspectiveWindow; +class PerspectiveMain; class PerspectiveConfig { @@ -45,14 +51,11 @@ public: int equivalent(PerspectiveConfig &that); void copy_from(PerspectiveConfig &that); - void interpolate(PerspectiveConfig &prev, - PerspectiveConfig &next, - int64_t prev_frame, - int64_t next_frame, - int64_t current_frame); + void interpolate(PerspectiveConfig &prev, PerspectiveConfig &next, + int64_t prev_frame, int64_t next_frame, int64_t current_frame); float x1, y1, x2, y2, x3, y3, x4, y4; - int mode; + int mode, smoothing; int window_w, window_h; int current_point; int forward; @@ -64,22 +67,13 @@ class PerspectiveCanvas : public BC_SubWindow { public: PerspectiveCanvas(PerspectiveMain *plugin, - int x, - int y, - int w, - int h); + int x, int y, int w, int h); int button_press_event(); int button_release_event(); int cursor_motion_event(); - int state; - enum - { - NONE, - DRAG, - DRAG_FULL, - ZOOM - }; + int state; + enum { NONE, DRAG, DRAG_FULL, ZOOM }; int start_cursor_x, start_cursor_y; float start_x1, start_y1; @@ -94,10 +88,7 @@ class PerspectiveCoord : public BC_TumbleTextBox public: PerspectiveCoord(PerspectiveWindow *gui, PerspectiveMain *plugin, - int x, - int y, - float value, - int is_x); + int x, int y, float value, int is_x); int handle_event(); PerspectiveMain *plugin; int is_x; @@ -107,8 +98,7 @@ class PerspectiveReset : public BC_GenericButton { public: PerspectiveReset(PerspectiveMain *plugin, - int x, - int y); + int x, int y); int handle_event(); PerspectiveMain *plugin; }; @@ -117,10 +107,7 @@ class PerspectiveMode : public BC_Radial { public: PerspectiveMode(PerspectiveMain *plugin, - int x, - int y, - int value, - char *text); + int x, int y, int value, char *text); int handle_event(); PerspectiveMain *plugin; int value; @@ -130,15 +117,42 @@ class PerspectiveDirection : public BC_Radial { public: PerspectiveDirection(PerspectiveMain *plugin, - int x, - int y, - int value, - char *text); + int x, int y, int value, char *text); int handle_event(); PerspectiveMain *plugin; int value; }; +class PerspectiveAffine : public BC_PopupMenu +{ + static const int n_modes = AffineEngine::AF_MODES; + const char *affine_modes[n_modes]; + PerspectiveAffineItem *affine_items[n_modes]; +public: + PerspectiveAffine(PerspectiveWindow *gui, int x, int y); + ~PerspectiveAffine(); + + void create_objects(); + void update(int mode, int send=1); + void affine_item(int id); + + PerspectiveWindow *gui; + int mode; +}; + +class PerspectiveAffineItem : public BC_MenuItem +{ +public: + PerspectiveAffineItem(const char *txt, int id) + : BC_MenuItem(txt) { this->id = id; } + + int handle_event(); + PerspectiveWindow *gui; + int id; +}; + + + class PerspectiveWindow : public PluginClientWindow { public: @@ -150,28 +164,20 @@ public: void update_canvas(); void update_mode(); void update_coord(); - void calculate_canvas_coords(int &x1, - int &y1, - int &x2, - int &y2, - int &x3, - int &y3, - int &x4, - int &y4); + void calculate_canvas_coords( + int &x1, int &y1, int &x2, int &y2, + int &x3, int &y3, int &x4, int &y4); PerspectiveCanvas *canvas; PerspectiveCoord *x, *y; PerspectiveReset *reset; PerspectiveMode *mode_perspective, *mode_sheer, *mode_stretch; + PerspectiveAffine *affine; PerspectiveMain *plugin; PerspectiveDirection *forward, *reverse; }; - - - - class PerspectiveMain : public PluginVClient { public: @@ -199,13 +205,3 @@ public: }; - - - - - - - - - - -- 2.26.2