X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;ds=sidebyside;f=cinelerra-5.1%2Fcinelerra%2Faffine.C;h=a59d6e3ee9997372f5b9c4eede18f44ac0d96a17;hb=502b6f3b6fd04f6b01c6d70dcb81aa304dd0db1c;hp=f5f90a7c8228c7ee8680a8576e61e2fd31b02953;hpb=680d2000be2db33da1e2733461854158067f5862;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/cinelerra/affine.C b/cinelerra-5.1/cinelerra/affine.C index f5f90a7c..a59d6e3e 100644 --- a/cinelerra-5.1/cinelerra/affine.C +++ b/cinelerra-5.1/cinelerra/affine.C @@ -25,6 +25,7 @@ #endif #include "affine.h" +#include "interp.h" #include "clip.h" #include "vframe.h" @@ -144,6 +145,38 @@ void AffineMatrix::copy_from(AffineMatrix *src) memcpy(&values[0][0], &src->values[0][0], sizeof(values)); } +void AffineMatrix::set_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 scalex = in_x2 > in_x1 ? 1./(in_x2 - in_x1) : 1.0; + double scaley = in_y2 > in_y1 ? 1./(in_y2 - in_y1) : 1.0; + double dx1 = out_x2 - out_x4, dx2 = out_x3 - out_x4; + double dx3 = out_x1 - out_x2 + out_x4 - out_x3; + + double dy1 = out_y2 - out_y4, dy2 = out_y3 - out_y4; + double dy3 = out_y1 - out_y2 + out_y4 - out_y3; + double det = dx1 * dy2 - dy1 * dx2; + if( !det ) { identity(); return; } + + AffineMatrix m; + m.values[2][0] = (dx3 * dy2 - dy3 * dx2) / det; + m.values[2][1] = (dx1 * dy3 - dy1 * dx3) / det; + m.values[0][0] = out_x2 - out_x1 + m.values[2][0] * out_x2; + m.values[0][1] = out_x3 - out_x1 + m.values[2][1] * out_x3; + m.values[0][2] = out_x1; + m.values[1][0] = out_y2 - out_y1 + m.values[2][0] * out_y2; + m.values[1][1] = out_y3 - out_y1 + m.values[2][1] * out_y3; + m.values[1][2] = out_y1; + m.values[2][2] = 1.0; + + identity(); + translate(-in_x1, -in_y1); + scale(scalex, scaley); + m.multiply(this); +} + void AffineMatrix::transform_point(float x, float y, float *newx, @@ -185,91 +218,6 @@ 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, - AffineMatrix *result) -{ - AffineMatrix matrix; - double scalex; - double scaley; - - scalex = scaley = 1.0; - - 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); - -/* Determine the perspective transform that maps from - * the unit cube to the transformed coordinates - */ - 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; - - 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 ); - -/* 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; - -// printf("AffineUnit::calculate_matrix 1 %f %f\n", dx3, dy3); -// matrix.dump(); - - result->identity(); - 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 } }; -// 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 p0, float p1, float p2, float p3) { @@ -409,12 +357,11 @@ void AffineUnit::process_package(LoadPackage *package) if( server->mode != AffineEngine::TRANSFORM ) { - calculate_matrix( server->in_x, server->in_y, + matrix.set_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, - &matrix); + out_x3, out_y3, out_x4, out_y4); } else { matrix.copy_from(&server->matrix); @@ -429,7 +376,6 @@ void AffineUnit::process_package(LoadPackage *package) float xinc, yinc, winc; AffineMatrix m, im; float ttx = 0, tty = 0; - int itx = 0, ity = 0; int tx1 = 0, ty1 = 0, tx2 = 0, ty2 = 0; if(reverse) { @@ -491,9 +437,7 @@ void AffineUnit::process_package(LoadPackage *package) server->output->to_texture(); server->output->enable_opengl(); - unsigned int frag_shader = VFrame::make_shader(0, - affine_frag, - 0); + unsigned int frag_shader = VFrame::make_shader(0, affine_frag, 0); if( frag_shader > 0 ) { glUseProgram(frag_shader); glUniform1i(glGetUniformLocation(frag_shader, "tex"), 0); @@ -555,172 +499,15 @@ void AffineUnit::process_package(LoadPackage *package) //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) ( !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_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; \ @@ -731,25 +518,21 @@ case tag: { \ 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 && itxinterpolation ) { 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); + DO_INTERP( BC_RGB_FLOAT, nearest, 3, float, float, 0x0, 1.0); + DO_INTERP( BC_RGB888, nearest, 3, unsigned char, int, 0x0, 0xff); + DO_INTERP( BC_RGBA_FLOAT, nearest, 4, float, float, 0x0, 1.0); + DO_INTERP( BC_RGBA8888, nearest, 4, unsigned char, int, 0x0, 0xff); + DO_INTERP( BC_YUV888, nearest, 3, unsigned char, int, 0x80, 0xff); + DO_INTERP( BC_YUVA8888, nearest, 4, unsigned char, int, 0x80, 0xff); + DO_INTERP( BC_RGB161616, nearest, 3, uint16_t, int, 0x0, 0xffff); + DO_INTERP( BC_RGBA16161616, nearest, 4, uint16_t, int, 0x0, 0xffff); + DO_INTERP( BC_YUV161616, nearest, 3, uint16_t, int, 0x8000, 0xffff); + DO_INTERP( BC_YUVA16161616, nearest, 4, uint16_t, int, 0x8000, 0xffff); } 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); + DO_INTERP( BC_RGB_FLOAT, bi_linear, 3, float, float, 0x0, 1.0); + DO_INTERP( BC_RGB888, bi_linear, 3, unsigned char, int, 0x0, 0xff); + DO_INTERP( BC_RGBA_FLOAT, bi_linear, 4, float, float, 0x0, 1.0); + DO_INTERP( BC_RGBA8888, bi_linear, 4, unsigned char, int, 0x0, 0xff); + DO_INTERP( BC_YUV888, bi_linear, 3, unsigned char, int, 0x80, 0xff); + DO_INTERP( BC_YUVA8888, bi_linear, 4, unsigned char, int, 0x80, 0xff); + DO_INTERP( BC_RGB161616, bi_linear, 3, uint16_t, int, 0x0, 0xffff); + DO_INTERP( BC_RGBA16161616, bi_linear, 4, uint16_t, int, 0x0, 0xffff); + DO_INTERP( BC_YUV161616, bi_linear, 3, uint16_t, int, 0x8000, 0xffff); + DO_INTERP( BC_YUVA16161616, bi_linear, 4, uint16_t, int, 0x8000, 0xffff); } 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); + DO_INTERP( BC_RGB_FLOAT, bi_cubic, 3, float, float, 0x0, 1.0); + DO_INTERP( BC_RGB888, bi_cubic, 3, unsigned char, int, 0x0, 0xff); + DO_INTERP( BC_RGBA_FLOAT, bi_cubic, 4, float, float, 0x0, 1.0); + DO_INTERP( BC_RGBA8888, bi_cubic, 4, unsigned char, int, 0x0, 0xff); + DO_INTERP( BC_YUV888, bi_cubic, 3, unsigned char, int, 0x80, 0xff); + DO_INTERP( BC_YUVA8888, bi_cubic, 4, unsigned char, int, 0x80, 0xff); + DO_INTERP( BC_RGB161616, bi_cubic, 3, uint16_t, int, 0x0, 0xffff); + DO_INTERP( BC_RGBA16161616, bi_cubic, 4, uint16_t, int, 0x0, 0xffff); + DO_INTERP( BC_YUV161616, bi_cubic, 3, uint16_t, int, 0x8000, 0xffff); + DO_INTERP( BC_YUVA16161616, bi_cubic, 4, uint16_t, int, 0x8000, 0xffff); } break; } @@ -978,7 +761,14 @@ void AffineEngine::process(VFrame *output, VFrame *input, VFrame *temp, int mode } } - +void AffineEngine::set_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) +{ + matrix.set_matrix(in_x1, in_y1, in_x2, in_y2, + out_x1, out_y1, out_x2, out_y2, out_x3, out_y3, out_x4, out_y4); +} void AffineEngine::rotate(VFrame *output, @@ -1066,15 +856,6 @@ 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 ) { - this->matrix.values[i][j] = matrix->values[i][j]; - } - } -} - void AffineEngine::set_in_viewport(int x, int y, int w, int h) { this->in_x = x; this->in_y = y;