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);
}
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;
}
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)
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;
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;
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();
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;
}
// 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;
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;
// 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;
#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
- 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;
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;
// 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"
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());
(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);
#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<max_in_x ? in_row[cp*comps]-chroma_offset : 0, \
+ c0>=min_in_x && c0<max_in_x ? in_row[c0*comps]-chroma_offset : 0, \
+ c1>=min_in_x && c1<max_in_x ? in_row[c1*comps]-chroma_offset : 0, \
+ c2>=min_in_x && c2<max_in_x ? in_row[c2*comps]-chroma_offset : 0) )
+
+
+#define DO_CUBIC(tag, components, type, temp_type, chroma_offset, max) \
+case tag: { \
+ type **inp_rows = (type**)server->input->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<ty2; ++y ) { \
+ type *out_row = (type*)out_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 * components; \
- for(int x = tx1; x < tx2; x++) \
- { \
+ int x1 = tx1, x2 = tx2; \
+ if( x1 < min_out_x ) x1 = min_out_x; \
+ if( x2 > 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<x2; ++x ) { \
/* Normalize homogeneous coords */ \
- if(tw == 0.0) \
- { \
- ttx = 0.0; \
- tty = 0.0; \
- } \
- else \
- if(tw != 1.0) \
- { \
- ttx = tx / tw; \
- tty = ty / tw; \
- } \
- else \
- { \
- ttx = tx; \
- tty = ty; \
- } \
- 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) \
- { \
- 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<max_in_y ? inp_rows[rp] : 0; \
+ r0p = r0>=min_in_y && r0<max_in_y ? inp_rows[r0] : 0; \
+ r1p = r1>=min_in_y && r1<max_in_y ? inp_rows[r1] : 0; \
+ r2p = r2>=min_in_y && r2<max_in_y ? inp_rows[r2] : 0; \
+ temp_type r, g, b, a; \
+ r = (temp_type)(transform_cubic(dy, \
+ CUBIC_ROW(rpp, 0x0), CUBIC_ROW(r0p, 0x0), \
+ CUBIC_ROW(r1p, 0x0), CUBIC_ROW(r2p, 0x0)) \
+ + round_factor); \
+ if(rpp) ++rpp; if(r0p) ++r0p; if(r1p) ++r1p; if(r2p) ++r2p; \
+ g = (temp_type)(transform_cubic(dy, \
+ CUBIC_ROW(rpp, chroma_offset), CUBIC_ROW(r0p, chroma_offset), \
+ CUBIC_ROW(r1p, chroma_offset), CUBIC_ROW(r2p, chroma_offset)) \
+ + round_factor) + chroma_offset; \
+ if(rpp) ++rpp; if(r0p) ++r0p; if(r1p) ++r1p; if(r2p) ++r2p; \
+ b = (temp_type)(transform_cubic(dy, \
+ CUBIC_ROW(rpp, chroma_offset), CUBIC_ROW(r0p, chroma_offset), \
+ CUBIC_ROW(r1p, chroma_offset), CUBIC_ROW(r2p, chroma_offset)) \
+ + round_factor) + chroma_offset; \
+ if( components == 4 ) { \
+ if(rpp) ++rpp; if(r0p) ++r0p; if(r1p) ++r1p; if(r2p) ++r2p; \
+ a = (temp_type)(transform_cubic(dy, \
+ CUBIC_ROW(rpp, 0x0), CUBIC_ROW(r0p, 0x0), \
+ CUBIC_ROW(r1p, 0x0), CUBIC_ROW(r2p, 0x0)) \
+ + round_factor); \
+ } \
+ if( sizeof(type) < 4 ) { \
+ *out++ = CLIP(r, 0, max); \
+ *out++ = CLIP(g, 0, max); \
+ *out++ = CLIP(b, 0, max); \
+ if( components == 4 ) *out++ = CLIP(a, 0, max); \
+ } \
+ else { \
+ *out++ = r; \
+ *out++ = g; \
+ *out++ = b; \
+ if( components == 4 ) *out++ = a; \
+ } \
\
- type *row1_ptr = in_rows[row1]; \
- type *row2_ptr = in_rows[row2]; \
- type *row3_ptr = in_rows[row3]; \
- type *row4_ptr = in_rows[row4]; \
- temp_type r, g, b, a; \
- \
- r = (temp_type)(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 = (temp_type)(transform_cubic(dy, \
- CUBIC_ROW(row1_ptr, chroma_offset), \
- CUBIC_ROW(row2_ptr, chroma_offset), \
- CUBIC_ROW(row3_ptr, chroma_offset), \
- CUBIC_ROW(row4_ptr, chroma_offset)) + \
- round_factor); \
- g += chroma_offset; \
+/* increment the transformed coordinates */ \
+ tx += xinc; ty += yinc; tw += winc; \
+ } \
+ } \
+} break
+
+#define LINEAR_ROW(in_row, chroma_offset) ( !in_row ? 0 : transform_linear(dx, \
+ c0>=min_in_x && c0<max_in_x ? in_row[c0*comps]-chroma_offset : 0, \
+ c1>=min_in_x && c1<max_in_x ? in_row[c1*comps]-chroma_offset : 0) )
+
+#define DO_LINEAR(tag, components, type, temp_type, chroma_offset, max) \
+case tag: { \
+ type **inp_rows = (type**)server->input->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<ty2; ++y ) { \
+ type *out_row = (type*)out_rows[y]; \
\
- row1_ptr++; \
- row2_ptr++; \
- row3_ptr++; \
- row4_ptr++; \
- b = (temp_type)(transform_cubic(dy, \
- CUBIC_ROW(row1_ptr, chroma_offset), \
- CUBIC_ROW(row2_ptr, chroma_offset), \
- CUBIC_ROW(row3_ptr, chroma_offset), \
- CUBIC_ROW(row4_ptr, chroma_offset)) + \
- round_factor); \
- b += chroma_offset; \
+ int x1 = tx1, x2 = tx2; \
+ if( x1 < min_out_x ) x1 = min_out_x; \
+ if( x2 > 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<x2; ++x ) { \
+/* Normalize homogeneous coords */ \
+ 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 */ \
+ float dx = ttx - itx, dy = tty - ity; \
+ if( dx < 0 ) dx += 1; \
+ if( dy < 0 ) dy += 1; \
+/* row/col index */ \
+ int c0 = itx+0, c1 = itx+1; \
+ int r0 = ity+0, r1 = ity+1; \
+ type *r0p, *r1p; \
+ r0p = r0>=min_in_y && r0<max_in_y ? inp_rows[r0] : 0; \
+ r1p = r1>=min_in_y && r1<max_in_y ? inp_rows[r1] : 0; \
+ temp_type r, g, b, a; \
+ r = (temp_type)(transform_linear(dy, \
+ LINEAR_ROW(r0p, 0x0), LINEAR_ROW(r1p, 0x0)) \
+ + round_factor); \
+ if(r0p) ++r0p; if(r1p) ++r1p; \
+ g = (temp_type)(transform_linear(dy, \
+ LINEAR_ROW(r0p, chroma_offset), LINEAR_ROW(r1p, chroma_offset)) \
+ + round_factor) + chroma_offset; \
+ if(r0p) ++r0p; if(r1p) ++r1p; \
+ b = (temp_type)(transform_linear(dy, \
+ LINEAR_ROW(r0p, chroma_offset), LINEAR_ROW(r1p, chroma_offset)) \
+ + round_factor) + chroma_offset; \
+ if( components == 4 ) { \
+ if(r0p) ++r0p; if(r1p) ++r1p; \
+ a = (temp_type)(transform_linear(dy, \
+ LINEAR_ROW(r0p, 0x0), LINEAR_ROW(r1p, 0x0)) \
+ + round_factor); \
+ } \
+ if( sizeof(type) < 4 ) { \
+ *out++ = CLIP(r, 0, max); \
+ *out++ = CLIP(g, 0, max); \
+ *out++ = CLIP(b, 0, max); \
+ if( components == 4 ) *out++ = CLIP(a, 0, max); \
+ } \
+ else { \
+ *out++ = r; \
+ *out++ = g; \
+ *out++ = b; \
+ if( components == 4 ) *out++ = a; \
+ } \
\
- if(components == 4) \
- { \
- row1_ptr++; \
- row2_ptr++; \
- row3_ptr++; \
- row4_ptr++; \
- a = (temp_type)(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); \
- } \
+/* increment the transformed coordinates */ \
+ tx += xinc; ty += yinc; tw += winc; \
+ } \
+ } \
+} break
+
+#define DO_NEAREST(tag, components, type, temp_type, chroma_offset, max) \
+case tag: { \
+ type **inp_rows = (type**)server->input->get_rows(); \
+ type **out_rows = (type**)server->output->get_rows(); \
+ for( int y=ty1; y<ty2; ++y ) { \
+ type *out_row = (type*)out_rows[y]; \
\
- if(sizeof(type) < 4) \
- { \
- *out_row++ = CLIP(r, 0, max); \
- *out_row++ = CLIP(g, 0, max); \
- *out_row++ = CLIP(b, 0, max); \
- if(components == 4) *out_row++ = CLIP(a, 0, max); \
- } \
- else \
- { \
- *out_row++ = r; \
- *out_row++ = g; \
- *out_row++ = b; \
- if(components == 4) *out_row++ = a; \
- } \
- } \
- else \
-/* Fill with chroma */ \
- { \
- *out_row++ = 0; \
- *out_row++ = chroma_offset; \
- *out_row++ = chroma_offset; \
- if(components == 4) *out_row++ = 0; \
- } \
- } \
- else \
- { \
- out_row += components; \
- } \
+ int x1 = tx1, x2 = tx2; \
+ if( x1 < min_out_x ) x1 = min_out_x; \
+ if( x2 > 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<x2; ++x ) { \
+/* Normalize homogeneous coords */ \
+ if( tw == 0.0 ) { ttx = 0.0; tty = 0.0; } \
+ else { ttx = tx / tw; tty = ty / tw; } \
+ itx = (int)ttx; ity = (int)tty; \
+/* row/col index */ \
+ type *rp = ity>=min_in_y && ity<max_in_y ? inp_rows[ity] : 0; \
+ temp_type r, g, b, a; \
+ r = (temp_type)( rp && itx>=min_in_x && itx<max_in_x ? rp[itx*components] : 0 ); \
+ if(rp) ++rp; \
+ g = (temp_type)( rp && itx>=min_in_x && itx<max_in_x ? rp[itx*components] : 0 ); \
+ if(rp) ++rp; \
+ b = (temp_type)( rp && itx>=min_in_x && itx<max_in_x ? rp[itx*components] : 0 ); \
+ if( components == 4 ) { \
+ if(rp) ++rp; \
+ a = (temp_type)( rp && itx>=min_in_x && itx<max_in_x ? rp[itx*components] : 0 ); \
+ } \
+ *out++ = r; *out++ = g; *out++ = b; \
+ if( components == 4 ) *out++ = a; \
\
/* increment the transformed coordinates */ \
- tx += xinc; \
- ty += yinc; \
- tw += winc; \
- } \
- } \
-}
-
-
-
+ tx += xinc; ty += yinc; tw += winc; \
+ } \
+ } \
+} break
// printf("AffineUnit::process_package %d tx1=%d ty1=%d tx2=%d ty2=%d\n",
// __LINE__, tx1, ty1, tx2, ty2);
- switch(server->input->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;
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(); \
\
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;
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; i<npkgs; ) {
AffinePackage *package = (AffinePackage*)get_package(i);
- package->y1 = 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;
}
}
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();
}
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
// 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;
}
//
// 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();
}
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];
}
}
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;
}
}
+void AffineEngine::set_interpolation(int type)
+{
+ interpolation = type;
+}
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;
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);
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;
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();
}
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,
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);
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;
}
-
-
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;
}
-
-
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();
// 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;
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();
int PerspectiveCanvas::button_release_event()
{
- if(state != PerspectiveCanvas::NONE)
- {
+ if( state != PerspectiveCanvas::NONE ) {
state = PerspectiveCanvas::NONE;
return 1;
}
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);
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;
}
-
-
-
-
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;
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();
}
-
-
-
-
-
-
-
-
-
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;
}
-
-
PerspectiveDirection::PerspectiveDirection(PerspectiveMain *plugin,
int x,
int y,
}
+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; id<n_modes; ++id )
+ delete affine_items[id];
+}
+void PerspectiveAffine::affine_item(int id)
+{
+ affine_items[id] = new PerspectiveAffineItem(affine_modes[id], id);
+ add_item(affine_items[id]);
+}
+void PerspectiveAffine::create_objects()
+{
+ affine_item(AffineEngine::AF_DEFAULT);
+ affine_item(AffineEngine::AF_NEAREST);
+ affine_item(AffineEngine::AF_LINEAR);
+ affine_item(AffineEngine::AF_CUBIC);
+ update(gui->plugin->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)
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");
- }
}
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);
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; i<h; ++i ) { \
+ type *out_row = (type*)output->get_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; j<w; ++j ) { \
+ out_row[0] = \
+ ( in_row1[0] + in_row1[components + 0] + \
+ in_row2[0] + in_row2[components + 0] ) / os2; \
+ out_row[1] = \
+ ( in_row1[1] + in_row1[components + 1] + \
+ in_row2[1] + in_row2[components + 1] ) / os2; \
+ out_row[2] = \
+ ( in_row1[2] + in_row1[components + 2] + \
+ in_row2[2] + in_row2[components + 2] ) / os2; \
+ if( components == 4 ) { \
+ out_row[3] = \
+ ( in_row1[3] + in_row1[components + 3] + \
+ in_row2[3] + in_row2[components + 3] ) / os2; \
+ } \
+ out_row += components; \
+ in_row1 += components * os; \
+ in_row2 += components * os; \
+ } \
+ } \
+} break
+
+ switch( frame->get_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 );
}
}
{
#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
}
-
-
-
-
-