00001 #if defined(HAVE_CONFIG_H)
00002 #include "config.h"
00003 #endif
00004
00005 #ifdef HAVE_GL
00006 #define GL_GLEXT_PROTOTYPES
00007 #include <GL/gl.h>
00008 #endif
00009
00010 #include "affine.h"
00011 #include "clip.h"
00012 #include "vframe.h"
00013
00014
00015 #include <math.h>
00016 #include <stdint.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019
00020 AffineMatrix::AffineMatrix()
00021 {
00022 bzero(values, sizeof(values));
00023 }
00024
00025 void AffineMatrix::identity()
00026 {
00027 bzero(values, sizeof(values));
00028 values[0][0] = 1;
00029 values[1][1] = 1;
00030 values[2][2] = 1;
00031 }
00032
00033 void AffineMatrix::translate(double x, double y)
00034 {
00035 double g = values[2][0];
00036 double h = values[2][1];
00037 double i = values[2][2];
00038 values[0][0] += x * g;
00039 values[0][1] += x * h;
00040 values[0][2] += x * i;
00041 values[1][0] += y * g;
00042 values[1][1] += y * h;
00043 values[1][2] += y * i;
00044 }
00045
00046 void AffineMatrix::scale(double x, double y)
00047 {
00048 values[0][0] *= x;
00049 values[0][1] *= x;
00050 values[0][2] *= x;
00051
00052 values[1][0] *= y;
00053 values[1][1] *= y;
00054 values[1][2] *= y;
00055 }
00056
00057 void AffineMatrix::multiply(AffineMatrix *dst)
00058 {
00059 int i, j;
00060 AffineMatrix tmp;
00061 double t1, t2, t3;
00062
00063 for (i = 0; i < 3; i++)
00064 {
00065 t1 = values[i][0];
00066 t2 = values[i][1];
00067 t3 = values[i][2];
00068 for (j = 0; j < 3; j++)
00069 {
00070 tmp.values[i][j] = t1 * dst->values[0][j];
00071 tmp.values[i][j] += t2 * dst->values[1][j];
00072 tmp.values[i][j] += t3 * dst->values[2][j];
00073 }
00074 }
00075 dst->copy_from(&tmp);
00076 }
00077
00078 double AffineMatrix::determinant()
00079 {
00080 double determinant;
00081
00082 determinant =
00083 values[0][0] * (values[1][1] * values[2][2] - values[1][2] * values[2][1]);
00084 determinant -=
00085 values[1][0] * (values[0][1] * values[2][2] - values[0][2] * values[2][1]);
00086 determinant +=
00087 values[2][0] * (values[0][1] * values[1][2] - values[0][2] * values[1][1]);
00088
00089 return determinant;
00090 }
00091
00092 void AffineMatrix::invert(AffineMatrix *dst)
00093 {
00094 double det_1;
00095
00096 det_1 = determinant();
00097
00098 if(det_1 == 0.0)
00099 return;
00100
00101 det_1 = 1.0 / det_1;
00102
00103 dst->values[0][0] =
00104 (values[1][1] * values[2][2] - values[1][2] * values[2][1]) * det_1;
00105
00106 dst->values[1][0] =
00107 - (values[1][0] * values[2][2] - values[1][2] * values[2][0]) * det_1;
00108
00109 dst->values[2][0] =
00110 (values[1][0] * values[2][1] - values[1][1] * values[2][0]) * det_1;
00111
00112 dst->values[0][1] =
00113 - (values[0][1] * values[2][2] - values[0][2] * values[2][1] ) * det_1;
00114
00115 dst->values[1][1] =
00116 (values[0][0] * values[2][2] - values[0][2] * values[2][0]) * det_1;
00117
00118 dst->values[2][1] =
00119 - (values[0][0] * values[2][1] - values[0][1] * values[2][0]) * det_1;
00120
00121 dst->values[0][2] =
00122 (values[0][1] * values[1][2] - values[0][2] * values[1][1]) * det_1;
00123
00124 dst->values[1][2] =
00125 - (values[0][0] * values[1][2] - values[0][2] * values[1][0]) * det_1;
00126
00127 dst->values[2][2] =
00128 (values[0][0] * values[1][1] - values[0][1] * values[1][0]) * det_1;
00129 }
00130
00131 void AffineMatrix::copy_from(AffineMatrix *src)
00132 {
00133 memcpy(&values[0][0], &src->values[0][0], sizeof(values));
00134 }
00135
00136 void AffineMatrix::transform_point(float x,
00137 float y,
00138 float *newx,
00139 float *newy)
00140 {
00141 double w;
00142
00143 w = values[2][0] * x + values[2][1] * y + values[2][2];
00144
00145 if (w == 0.0)
00146 w = 1.0;
00147 else
00148 w = 1.0 / w;
00149
00150 *newx = (values[0][0] * x + values[0][1] * y + values[0][2]) * w;
00151 *newy = (values[1][0] * x + values[1][1] * y + values[1][2]) * w;
00152 }
00153
00154 void AffineMatrix::dump()
00155 {
00156 printf("AffineMatrix::dump\n");
00157 printf("%f %f %f\n", values[0][0], values[0][1], values[0][2]);
00158 printf("%f %f %f\n", values[1][0], values[1][1], values[1][2]);
00159 printf("%f %f %f\n", values[2][0], values[2][1], values[2][2]);
00160 }
00161
00162
00163
00164
00165
00166 AffinePackage::AffinePackage()
00167 : LoadPackage()
00168 {
00169 }
00170
00171
00172
00173
00174 AffineUnit::AffineUnit(AffineEngine *server)
00175 : LoadClient(server)
00176 {
00177 this->server = server;
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 void AffineUnit::calculate_matrix(
00189 double in_x1,
00190 double in_y1,
00191 double in_x2,
00192 double in_y2,
00193 double out_x1,
00194 double out_y1,
00195 double out_x2,
00196 double out_y2,
00197 double out_x3,
00198 double out_y3,
00199 double out_x4,
00200 double out_y4,
00201 AffineMatrix *result)
00202 {
00203 AffineMatrix matrix;
00204 double scalex;
00205 double scaley;
00206
00207 scalex = scaley = 1.0;
00208
00209 if((in_x2 - in_x1) > 0)
00210 scalex = 1.0 / (double)(in_x2 - in_x1);
00211
00212 if((in_y2 - in_y1) > 0)
00213 scaley = 1.0 / (double)(in_y2 - in_y1);
00214
00215
00216
00217
00218 double dx1, dx2, dx3, dy1, dy2, dy3;
00219 double det1, det2;
00220
00221 dx1 = out_x2 - out_x4;
00222 dx2 = out_x3 - out_x4;
00223 dx3 = out_x1 - out_x2 + out_x4 - out_x3;
00224
00225 dy1 = out_y2 - out_y4;
00226 dy2 = out_y3 - out_y4;
00227 dy3 = out_y1 - out_y2 + out_y4 - out_y3;
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 if((dx3 == 0.0) && (dy3 == 0.0))
00239 {
00240 matrix.values[0][0] = out_x2 - out_x1;
00241 matrix.values[0][1] = out_x4 - out_x2;
00242 matrix.values[0][2] = out_x1;
00243 matrix.values[1][0] = out_y2 - out_y1;
00244 matrix.values[1][1] = out_y4 - out_y2;
00245 matrix.values[1][2] = out_y1;
00246 matrix.values[2][0] = 0.0;
00247 matrix.values[2][1] = 0.0;
00248 }
00249 else
00250 {
00251 det1 = dx3 * dy2 - dy3 * dx2;
00252 det2 = dx1 * dy2 - dy1 * dx2;
00253 matrix.values[2][0] = det1 / det2;
00254 det1 = dx1 * dy3 - dy1 * dx3;
00255 det2 = dx1 * dy2 - dy1 * dx2;
00256 matrix.values[2][1] = det1 / det2;
00257
00258 matrix.values[0][0] = out_x2 - out_x1 + matrix.values[2][0] * out_x2;
00259 matrix.values[0][1] = out_x3 - out_x1 + matrix.values[2][1] * out_x3;
00260 matrix.values[0][2] = out_x1;
00261
00262 matrix.values[1][0] = out_y2 - out_y1 + matrix.values[2][0] * out_y2;
00263 matrix.values[1][1] = out_y3 - out_y1 + matrix.values[2][1] * out_y3;
00264 matrix.values[1][2] = out_y1;
00265 }
00266
00267 matrix.values[2][2] = 1.0;
00268
00269
00270
00271
00272 result->identity();
00273 result->translate(-in_x1, -in_y1);
00274 result->scale(scalex, scaley);
00275 matrix.multiply(result);
00276
00277
00278
00279
00280
00281
00282
00283
00284 }
00285
00286 float AffineUnit::transform_cubic(float dx,
00287 float jm1,
00288 float j,
00289 float jp1,
00290 float jp2)
00291 {
00292
00293 float result = ((( ( - jm1 + 3.0 * j - 3.0 * jp1 + jp2 ) * dx +
00294 ( 2.0 * jm1 - 5.0 * j + 4.0 * jp1 - jp2 ) ) * dx +
00295 ( - jm1 + jp1 ) ) * dx + (j + j) ) / 2.0;
00296
00297
00298
00299
00300
00301
00302
00303
00304 return result;
00305 }
00306
00307
00308 void AffineUnit::process_package(LoadPackage *package)
00309 {
00310 AffinePackage *pkg = (AffinePackage*)package;
00311 int minx = server->x;
00312 int miny = server->y;
00313 int maxx = server->x + server->w - 1;
00314 int maxy = server->y + server->h - 1;
00315
00316
00317 float out_x1, out_y1, out_x2, out_y2, out_x3, out_y3, out_x4, out_y4;
00318 if(server->mode == AffineEngine::STRETCH ||
00319 server->mode == AffineEngine::PERSPECTIVE ||
00320 server->mode == AffineEngine::ROTATE)
00321 {
00322 out_x1 = (float)server->x + (float)server->x1 * server->w / 100;
00323 out_y1 = (float)server->y + (float)server->y1 * server->h / 100;
00324 out_x2 = (float)server->x + (float)server->x2 * server->w / 100;
00325 out_y2 = (float)server->y + (float)server->y2 * server->h / 100;
00326 out_x3 = (float)server->x + (float)server->x3 * server->w / 100;
00327 out_y3 = (float)server->y + (float)server->y3 * server->h / 100;
00328 out_x4 = (float)server->x + (float)server->x4 * server->w / 100;
00329 out_y4 = (float)server->y + (float)server->y4 * server->h / 100;
00330 }
00331 else
00332 {
00333 out_x1 = (float)server->x + (float)server->x1 * server->w / 100;
00334 out_y1 = server->y;
00335 out_x2 = out_x1 + server->w;
00336 out_y2 = server->y;
00337 out_x4 = (float)server->x + (float)server->x4 * server->w / 100;
00338 out_y4 = server->y + server->h;
00339 out_x3 = out_x4 + server->w;
00340 out_y3 = server->y + server->h;
00341 }
00342
00343
00344
00345
00346 if(server->mode == AffineEngine::ROTATE &&
00347 server->use_opengl)
00348 {
00349 #ifdef HAVE_GL
00350 server->output->to_texture();
00351 server->output->enable_opengl();
00352 server->output->init_screen();
00353 server->output->bind_texture(0);
00354 server->output->clear_pbuffer();
00355
00356 int texture_w = server->output->get_texture_w();
00357 int texture_h = server->output->get_texture_h();
00358 float output_h = server->output->get_h();
00359 float in_x1 = (float)server->x / texture_w;
00360 float in_x2 = (float)(server->x + server->w) / texture_w;
00361 float in_y1 = (float)server->y / texture_h;
00362 float in_y2 = (float)(server->y + server->h) / texture_h;
00363
00364
00365
00366
00367 glBegin(GL_QUADS);
00368 glNormal3f(0, 0, 1.0);
00369
00370 glTexCoord2f(in_x1, in_y1);
00371 glVertex3f(out_x1, -output_h+out_y1, 0);
00372
00373 glTexCoord2f(in_x2, in_y1);
00374 glVertex3f(out_x2, -output_h+out_y2, 0);
00375
00376 glTexCoord2f(in_x2, in_y2);
00377 glVertex3f(out_x3, -output_h+out_y3, 0);
00378
00379 glTexCoord2f(in_x1, in_y2);
00380 glVertex3f(out_x4, -output_h+out_y4, 0);
00381
00382
00383 glEnd();
00384
00385 server->output->set_opengl_state(VFrame::SCREEN);
00386 #endif
00387 }
00388 else
00389 if(server->mode == AffineEngine::PERSPECTIVE ||
00390 server->mode == AffineEngine::SHEER ||
00391 server->mode == AffineEngine::ROTATE)
00392 {
00393 AffineMatrix matrix;
00394 float temp;
00395 temp = out_x4;
00396 out_x4 = out_x3;
00397 out_x3 = temp;
00398 temp = out_y4;
00399 out_y4 = out_y3;
00400 out_y3 = temp;
00401
00402
00403
00404
00405
00406
00407 calculate_matrix(
00408 server->x,
00409 server->y,
00410 server->x + server->w,
00411 server->y + server->h,
00412 out_x1,
00413 out_y1,
00414 out_x2,
00415 out_y2,
00416 out_x3,
00417 out_y3,
00418 out_x4,
00419 out_y4,
00420 &matrix);
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 int interpolate = 1;
00432 int reverse = !server->forward;
00433 float tx, ty, tw;
00434 float xinc, yinc, winc;
00435 AffineMatrix m, im;
00436 float ttx, tty;
00437 int itx, ity;
00438 int tx1, ty1, tx2, ty2;
00439
00440 if(reverse)
00441 {
00442 m.copy_from(&matrix);
00443 m.invert(&im);
00444 matrix.copy_from(&im);
00445 }
00446 else
00447 {
00448 matrix.invert(&m);
00449 }
00450
00451 float dx1, dy1;
00452 float dx2, dy2;
00453 float dx3, dy3;
00454 float dx4, dy4;
00455 matrix.transform_point(server->x, server->y, &dx1, &dy1);
00456 matrix.transform_point(server->x + server->w, server->y, &dx2, &dy2);
00457 matrix.transform_point(server->x, server->y + server->h, &dx3, &dy3);
00458 matrix.transform_point(server->x + server->w, server->y + server->h, &dx4, &dy4);
00459
00460
00461
00462
00463
00464
00465 if(server->use_opengl)
00466 {
00467 #ifdef HAVE_GL
00468 static char *affine_frag =
00469 "uniform sampler2D tex;\n"
00470 "uniform mat3 affine_matrix;\n"
00471 "uniform vec2 texture_extents;\n"
00472 "uniform vec2 image_extents;\n"
00473 "uniform vec4 border_color;\n"
00474 "void main()\n"
00475 "{\n"
00476 " vec2 outcoord = gl_TexCoord[0].st;\n"
00477 " outcoord *= texture_extents;\n"
00478 " mat3 coord_matrix = mat3(\n"
00479 " outcoord.x, outcoord.y, 1.0, \n"
00480 " outcoord.x, outcoord.y, 1.0, \n"
00481 " outcoord.x, outcoord.y, 1.0);\n"
00482 " mat3 incoord_matrix = affine_matrix * coord_matrix;\n"
00483 " vec2 incoord = vec2(incoord_matrix[0][0], incoord_matrix[0][1]);\n"
00484 " incoord /= incoord_matrix[0][2];\n"
00485 " incoord /= texture_extents;\n"
00486 " if(incoord.x > image_extents.x || incoord.y > image_extents.y)\n"
00487 " gl_FragColor = border_color;\n"
00488 " else\n"
00489 " gl_FragColor = texture2D(tex, incoord);\n"
00490 "}\n";
00491
00492 float affine_matrix[9] = {
00493 m.values[0][0], m.values[1][0], m.values[2][0],
00494 m.values[0][1], m.values[1][1], m.values[2][1],
00495 m.values[0][2], m.values[1][2], m.values[2][2]
00496 };
00497
00498
00499 server->output->to_texture();
00500 server->output->enable_opengl();
00501 unsigned int frag_shader = VFrame::make_shader(0,
00502 affine_frag,
00503 0);
00504 if(frag_shader > 0)
00505 {
00506 glUseProgram(frag_shader);
00507 glUniform1i(glGetUniformLocation(frag_shader, "tex"), 0);
00508 glUniformMatrix3fv(glGetUniformLocation(frag_shader, "affine_matrix"),
00509 1,
00510 0,
00511 affine_matrix);
00512 glUniform2f(glGetUniformLocation(frag_shader, "texture_extents"),
00513 (GLfloat)server->output->get_texture_w(),
00514 (GLfloat)server->output->get_texture_h());
00515 glUniform2f(glGetUniformLocation(frag_shader, "image_extents"),
00516 (GLfloat)server->output->get_w() / server->output->get_texture_w(),
00517 (GLfloat)server->output->get_h() / server->output->get_texture_h());
00518 float border_color[] = { 0, 0, 0, 0 };
00519 if(cmodel_is_yuv(server->output->get_color_model()))
00520 {
00521 border_color[1] = 0.5;
00522 border_color[2] = 0.5;
00523 }
00524 glUniform4fv(glGetUniformLocation(frag_shader, "border_color"),
00525 1,
00526 (GLfloat*)border_color);
00527 server->output->init_screen();
00528 server->output->bind_texture(0);
00529 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
00530 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
00531 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
00532 server->output->draw_texture();
00533 glUseProgram(0);
00534 server->output->set_opengl_state(VFrame::SCREEN);
00535 }
00536 return;
00537 #endif
00538 }
00539
00540
00541
00542
00543
00544
00545 #define ROUND(x) ((int)((x > 0) ? (x) + 0.5 : (x) - 0.5))
00546 #define MIN4(a,b,c,d) MIN(MIN(MIN(a,b),c),d)
00547 #define MAX4(a,b,c,d) MAX(MAX(MAX(a,b),c),d)
00548
00549 tx1 = ROUND(MIN4(dx1, dx2, dx3, dx4));
00550 ty1 = ROUND(MIN4(dy1, dy2, dy3, dy4));
00551
00552 tx2 = ROUND(MAX4(dx1, dx2, dx3, dx4));
00553 ty2 = ROUND(MAX4(dy1, dy2, dy3, dy4));
00554
00555 CLAMP(ty1, pkg->y1, pkg->y2);
00556 CLAMP(ty2, pkg->y1, pkg->y2);
00557
00558 xinc = m.values[0][0];
00559 yinc = m.values[1][0];
00560 winc = m.values[2][0];
00561
00562
00563 #define CUBIC_ROW(in_row, chroma_offset) \
00564 transform_cubic(dx, \
00565 in_row[col1_offset] - chroma_offset, \
00566 in_row[col2_offset] - chroma_offset, \
00567 in_row[col3_offset] - chroma_offset, \
00568 in_row[col4_offset] - chroma_offset)
00569
00570 #define TRANSFORM(components, type, temp_type, chroma_offset, max) \
00571 { \
00572 type **in_rows = (type**)server->input->get_rows(); \
00573 float round_factor = 0.0; \
00574 if(sizeof(type) < 4) round_factor = 0.5; \
00575 for(int y = ty1; y < ty2; y++) \
00576 { \
00577 type *out_row = (type*)server->output->get_rows()[y]; \
00578 \
00579 if(!interpolate) \
00580 { \
00581 tx = xinc * (tx1 + 0.5) + m.values[0][1] * (y + 0.5) + m.values[0][2]; \
00582 ty = yinc * (tx1 + 0.5) + m.values[1][1] * (y + 0.5) + m.values[1][2]; \
00583 tw = winc * (tx1 + 0.5) + m.values[2][1] * (y + 0.5) + m.values[2][2]; \
00584 } \
00585 else \
00586 { \
00587 tx = xinc * tx1 + m.values[0][1] * y + m.values[0][2]; \
00588 ty = yinc * tx1 + m.values[1][1] * y + m.values[1][2]; \
00589 tw = winc * tx1 + m.values[2][1] * y + m.values[2][2]; \
00590 } \
00591 \
00592 \
00593 out_row += tx1 * components; \
00594 for(int x = tx1; x < tx2; x++) \
00595 { \
00596 \
00597 if(tw == 0.0) \
00598 { \
00599 ttx = 0.0; \
00600 tty = 0.0; \
00601 } \
00602 else \
00603 if(tw != 1.0) \
00604 { \
00605 ttx = tx / tw; \
00606 tty = ty / tw; \
00607 } \
00608 else \
00609 { \
00610 ttx = tx; \
00611 tty = ty; \
00612 } \
00613 itx = (int)ttx; \
00614 ity = (int)tty; \
00615 \
00616 int row1 = ity - 1; \
00617 int row2 = ity; \
00618 int row3 = ity + 1; \
00619 int row4 = ity + 2; \
00620 CLAMP(row1, miny, maxy); \
00621 CLAMP(row2, miny, maxy); \
00622 CLAMP(row3, miny, maxy); \
00623 CLAMP(row4, miny, maxy); \
00624 \
00625 \
00626 if(!interpolate && x >= server->x && x < server->x + server->w) \
00627 { \
00628 if(itx >= server->x && itx < server->x + server->w && \
00629 ity >= server->y && ity < server->y + server->h) \
00630 { \
00631 type *src = in_rows[ity] + itx * components; \
00632 *out_row++ = *src++; \
00633 *out_row++ = *src++; \
00634 *out_row++ = *src++; \
00635 if(components == 4) *out_row++ = *src; \
00636 } \
00637 else \
00638 \
00639 { \
00640 *out_row++ = 0; \
00641 *out_row++ = chroma_offset; \
00642 *out_row++ = chroma_offset; \
00643 if(components == 4) *out_row++ = 0; \
00644 } \
00645 } \
00646 else \
00647 \
00648 if(interpolate && x >= server->x && x < server->x + server->w) \
00649 { \
00650 if ((itx + 2) >= server->x && (itx - 1) < server->x + server->w && \
00651 (ity + 2) >= server->y && (ity - 1) < server->y + server->h) \
00652 { \
00653 float dx, dy; \
00654 \
00655 \
00656 dx = ttx - itx; \
00657 dy = tty - ity; \
00658 \
00659 \
00660 int col1 = itx - 1; \
00661 int col2 = itx; \
00662 int col3 = itx + 1; \
00663 int col4 = itx + 2; \
00664 CLAMP(col1, minx, maxx); \
00665 CLAMP(col2, minx, maxx); \
00666 CLAMP(col3, minx, maxx); \
00667 CLAMP(col4, minx, maxx); \
00668 int col1_offset = col1 * components; \
00669 int col2_offset = col2 * components; \
00670 int col3_offset = col3 * components; \
00671 int col4_offset = col4 * components; \
00672 type *row1_ptr = in_rows[row1]; \
00673 type *row2_ptr = in_rows[row2]; \
00674 type *row3_ptr = in_rows[row3]; \
00675 type *row4_ptr = in_rows[row4]; \
00676 temp_type r, g, b, a; \
00677 \
00678 r = (temp_type)(transform_cubic(dy, \
00679 CUBIC_ROW(row1_ptr, 0x0), \
00680 CUBIC_ROW(row2_ptr, 0x0), \
00681 CUBIC_ROW(row3_ptr, 0x0), \
00682 CUBIC_ROW(row4_ptr, 0x0)) + \
00683 round_factor); \
00684 \
00685 row1_ptr++; \
00686 row2_ptr++; \
00687 row3_ptr++; \
00688 row4_ptr++; \
00689 g = (temp_type)(transform_cubic(dy, \
00690 CUBIC_ROW(row1_ptr, chroma_offset), \
00691 CUBIC_ROW(row2_ptr, chroma_offset), \
00692 CUBIC_ROW(row3_ptr, chroma_offset), \
00693 CUBIC_ROW(row4_ptr, chroma_offset)) + \
00694 round_factor); \
00695 g += chroma_offset; \
00696 \
00697 row1_ptr++; \
00698 row2_ptr++; \
00699 row3_ptr++; \
00700 row4_ptr++; \
00701 b = (temp_type)(transform_cubic(dy, \
00702 CUBIC_ROW(row1_ptr, chroma_offset), \
00703 CUBIC_ROW(row2_ptr, chroma_offset), \
00704 CUBIC_ROW(row3_ptr, chroma_offset), \
00705 CUBIC_ROW(row4_ptr, chroma_offset)) + \
00706 round_factor); \
00707 b += chroma_offset; \
00708 \
00709 if(components == 4) \
00710 { \
00711 row1_ptr++; \
00712 row2_ptr++; \
00713 row3_ptr++; \
00714 row4_ptr++; \
00715 a = (temp_type)(transform_cubic(dy, \
00716 CUBIC_ROW(row1_ptr, 0x0), \
00717 CUBIC_ROW(row2_ptr, 0x0), \
00718 CUBIC_ROW(row3_ptr, 0x0), \
00719 CUBIC_ROW(row4_ptr, 0x0)) + \
00720 round_factor); \
00721 } \
00722 \
00723 if(sizeof(type) < 4) \
00724 { \
00725 *out_row++ = CLIP(r, 0, max); \
00726 *out_row++ = CLIP(g, 0, max); \
00727 *out_row++ = CLIP(b, 0, max); \
00728 if(components == 4) *out_row++ = CLIP(a, 0, max); \
00729 } \
00730 else \
00731 { \
00732 *out_row++ = r; \
00733 *out_row++ = g; \
00734 *out_row++ = b; \
00735 if(components == 4) *out_row++ = a; \
00736 } \
00737 } \
00738 else \
00739 \
00740 { \
00741 *out_row++ = 0; \
00742 *out_row++ = chroma_offset; \
00743 *out_row++ = chroma_offset; \
00744 if(components == 4) *out_row++ = 0; \
00745 } \
00746 } \
00747 else \
00748 { \
00749 out_row += components; \
00750 } \
00751 \
00752 \
00753 tx += xinc; \
00754 ty += yinc; \
00755 tw += winc; \
00756 } \
00757 } \
00758 }
00759
00760
00761
00762
00763 switch(server->input->get_color_model())
00764 {
00765 case BC_RGB_FLOAT:
00766 TRANSFORM(3, float, float, 0x0, 1.0)
00767 break;
00768 case BC_RGB888:
00769 TRANSFORM(3, unsigned char, int, 0x0, 0xff)
00770 break;
00771 case BC_RGBA_FLOAT:
00772 TRANSFORM(4, float, float, 0x0, 1.0)
00773 break;
00774 case BC_RGBA8888:
00775 TRANSFORM(4, unsigned char, int, 0x0, 0xff)
00776 break;
00777 case BC_YUV888:
00778 TRANSFORM(3, unsigned char, int, 0x80, 0xff)
00779 break;
00780 case BC_YUVA8888:
00781 TRANSFORM(4, unsigned char, int, 0x80, 0xff)
00782 break;
00783 case BC_RGB161616:
00784 TRANSFORM(3, uint16_t, int, 0x0, 0xffff)
00785 break;
00786 case BC_RGBA16161616:
00787 TRANSFORM(4, uint16_t, int, 0x0, 0xffff)
00788 break;
00789 case BC_YUV161616:
00790 TRANSFORM(3, uint16_t, int, 0x8000, 0xffff)
00791 break;
00792 case BC_YUVA16161616:
00793 TRANSFORM(4, uint16_t, int, 0x8000, 0xffff)
00794 break;
00795 }
00796
00797 }
00798 else
00799 {
00800 int min_x = server->x * AFFINE_OVERSAMPLE;
00801 int min_y = server->y * AFFINE_OVERSAMPLE;
00802 int max_x = server->x * AFFINE_OVERSAMPLE + server->w * AFFINE_OVERSAMPLE - 1;
00803 int max_y = server->y * AFFINE_OVERSAMPLE + server->h * AFFINE_OVERSAMPLE - 1;
00804 float top_w = out_x2 - out_x1;
00805 float bottom_w = out_x3 - out_x4;
00806 float left_h = out_y4 - out_y1;
00807 float right_h = out_y3 - out_y2;
00808 float out_w_diff = bottom_w - top_w;
00809 float out_left_diff = out_x4 - out_x1;
00810 float out_h_diff = right_h - left_h;
00811 float out_top_diff = out_y2 - out_y1;
00812 float distance1 = DISTANCE(out_x1, out_y1, out_x2, out_y2);
00813 float distance2 = DISTANCE(out_x2, out_y2, out_x3, out_y3);
00814 float distance3 = DISTANCE(out_x3, out_y3, out_x4, out_y4);
00815 float distance4 = DISTANCE(out_x4, out_y4, out_x1, out_y1);
00816 float max_v = MAX(distance1, distance3);
00817 float max_h = MAX(distance2, distance4);
00818 float max_dimension = MAX(max_v, max_h);
00819 float min_dimension = MIN(server->h, server->w);
00820 float step = min_dimension / max_dimension / AFFINE_OVERSAMPLE;
00821 float x_f = server->x;
00822 float y_f = server->y;
00823 float h_f = server->h;
00824 float w_f = server->w;
00825
00826
00827
00828 if(server->use_opengl)
00829 {
00830 return;
00831 }
00832
00833
00834
00835
00836 #define DO_STRETCH(type, components) \
00837 { \
00838 type **in_rows = (type**)server->input->get_rows(); \
00839 type **out_rows = (type**)server->temp->get_rows(); \
00840 \
00841 for(float in_y = pkg->y1; in_y < pkg->y2; in_y += step) \
00842 { \
00843 int i = (int)in_y; \
00844 type *in_row = in_rows[i]; \
00845 for(float in_x = x_f; in_x < w_f; in_x += step) \
00846 { \
00847 int j = (int)in_x; \
00848 float in_x_fraction = (in_x - x_f) / w_f; \
00849 float in_y_fraction = (in_y - y_f) / h_f; \
00850 int out_x = (int)((out_x1 + \
00851 out_left_diff * in_y_fraction + \
00852 (top_w + out_w_diff * in_y_fraction) * in_x_fraction) * \
00853 AFFINE_OVERSAMPLE); \
00854 int out_y = (int)((out_y1 + \
00855 out_top_diff * in_x_fraction + \
00856 (left_h + out_h_diff * in_x_fraction) * in_y_fraction) * \
00857 AFFINE_OVERSAMPLE); \
00858 CLAMP(out_x, min_x, max_x); \
00859 CLAMP(out_y, min_y, max_y); \
00860 type *dst = out_rows[out_y] + out_x * components; \
00861 type *src = in_row + j * components; \
00862 dst[0] = src[0]; \
00863 dst[1] = src[1]; \
00864 dst[2] = src[2]; \
00865 if(components == 4) dst[3] = src[3]; \
00866 } \
00867 } \
00868 }
00869
00870 switch(server->input->get_color_model())
00871 {
00872 case BC_RGB_FLOAT:
00873 DO_STRETCH(float, 3)
00874 break;
00875 case BC_RGB888:
00876 DO_STRETCH(unsigned char, 3)
00877 break;
00878 case BC_RGBA_FLOAT:
00879 DO_STRETCH(float, 4)
00880 break;
00881 case BC_RGBA8888:
00882 DO_STRETCH(unsigned char, 4)
00883 break;
00884 case BC_YUV888:
00885 DO_STRETCH(unsigned char, 3)
00886 break;
00887 case BC_YUVA8888:
00888 DO_STRETCH(unsigned char, 4)
00889 break;
00890 case BC_RGB161616:
00891 DO_STRETCH(uint16_t, 3)
00892 break;
00893 case BC_RGBA16161616:
00894 DO_STRETCH(uint16_t, 4)
00895 break;
00896 case BC_YUV161616:
00897 DO_STRETCH(uint16_t, 3)
00898 break;
00899 case BC_YUVA16161616:
00900 DO_STRETCH(uint16_t, 4)
00901 break;
00902 }
00903 }
00904
00905
00906
00907
00908 }
00909
00910
00911
00912
00913
00914
00915 AffineEngine::AffineEngine(int total_clients,
00916 int total_packages)
00917 : LoadServer(
00918
00919 total_clients, total_packages
00920 )
00921 {
00922 user_viewport = 0;
00923 user_pivot = 0;
00924 use_opengl = 0;
00925 }
00926
00927 void AffineEngine::init_packages()
00928 {
00929 for(int i = 0; i < get_total_packages(); i++)
00930 {
00931 AffinePackage *package = (AffinePackage*)get_package(i);
00932 package->y1 = y + (h * i / get_total_packages());
00933 package->y2 = y + (h * (i + 1) / get_total_packages());
00934 }
00935 }
00936
00937 LoadClient* AffineEngine::new_client()
00938 {
00939 return new AffineUnit(this);
00940 }
00941
00942 LoadPackage* AffineEngine::new_package()
00943 {
00944 return new AffinePackage;
00945 }
00946
00947 void AffineEngine::process(VFrame *output,
00948 VFrame *input,
00949 VFrame *temp,
00950 int mode,
00951 float x1,
00952 float y1,
00953 float x2,
00954 float y2,
00955 float x3,
00956 float y3,
00957 float x4,
00958 float y4,
00959 int forward)
00960 {
00961 this->output = output;
00962 this->input = input;
00963 this->temp = temp;
00964 this->mode = mode;
00965 this->x1 = x1;
00966 this->y1 = y1;
00967 this->x2 = x2;
00968 this->y2 = y2;
00969 this->x3 = x3;
00970 this->y3 = y3;
00971 this->x4 = x4;
00972 this->y4 = y4;
00973 this->forward = forward;
00974
00975
00976 if(!user_viewport)
00977 {
00978 x = 0;
00979 y = 0;
00980 w = input->get_w();
00981 h = input->get_h();
00982 }
00983
00984 if(use_opengl)
00985 process_single();
00986 else
00987 process_packages();
00988 }
00989
00990
00991
00992
00993 void AffineEngine::rotate(VFrame *output,
00994 VFrame *input,
00995 float angle)
00996 {
00997 this->output = output;
00998 this->input = input;
00999 this->temp = 0;
01000 this->mode = ROTATE;
01001 this->forward = 1;
01002
01003 if(!user_viewport)
01004 {
01005 x = 0;
01006 y = 0;
01007 w = input->get_w();
01008 h = input->get_h();
01009 }
01010
01011 if(!user_pivot)
01012 {
01013 pivot_x = x + w / 2;
01014 pivot_y = y + h / 2;
01015 }
01016
01017
01018 angle = angle * 2 * M_PI / 360;
01019 double angle1 = atan((double)(pivot_y - y) / (double)(pivot_x -