00001 #include <math.h>
00002 #include <stdio.h>
00003 #include <string.h>
00004 #include <stdint.h>
00005 #include <stdlib.h>
00006 #include <unistd.h>
00007
00008 #include "clip.h"
00009 #include "edl.inc"
00010 #include "mutex.h"
00011 #include "overlayframe.h"
00012 #include "units.h"
00013 #include "vframe.h"
00014
00015
00016
00017 static int my_abs(int32_t x)
00018 {
00019 return abs(x);
00020 }
00021
00022 static int my_abs(uint32_t x)
00023 {
00024 return x;
00025 }
00026
00027 static int my_abs(int64_t x)
00028 {
00029 return llabs(x);
00030 }
00031
00032 static int my_abs(uint64_t x)
00033 {
00034 return x;
00035 }
00036
00037 static float my_abs(float x)
00038 {
00039 return fabsf(x);
00040 }
00041
00042
00043
00044
00045 OverlayFrame::OverlayFrame(int cpus)
00046 {
00047 temp_frame = 0;
00048 blend_engine = 0;
00049 scale_engine = 0;
00050 scaletranslate_engine = 0;
00051 translate_engine = 0;
00052 this->cpus = cpus;
00053 }
00054
00055 OverlayFrame::~OverlayFrame()
00056 {
00057 if(temp_frame) delete temp_frame;
00058 if(scale_engine) delete scale_engine;
00059 if(translate_engine) delete translate_engine;
00060 if(blend_engine) delete blend_engine;
00061 if(scaletranslate_engine) delete scaletranslate_engine;
00062 }
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 #define BLEND_3(max, temp_type, type, chroma_offset) \
00083 { \
00084 temp_type r, g, b; \
00085 \
00086 \
00087 switch(mode) \
00088 { \
00089 case TRANSFER_DIVIDE: \
00090 r = input1 ? (((temp_type)output[0] * max) / input1) : max; \
00091 if(chroma_offset) \
00092 { \
00093 g = my_abs((temp_type)input2 - chroma_offset) > my_abs((temp_type)output[1] - chroma_offset) ? input2 : output[1]; \
00094 b = my_abs((temp_type)input3 - chroma_offset) > my_abs((temp_type)output[2] - chroma_offset) ? input3 : output[2]; \
00095 } \
00096 else \
00097 { \
00098 g = input2 ? (temp_type)output[1] * max / (temp_type)input2 : max; \
00099 b = input3 ? (temp_type)output[2] * max / (temp_type)input3 : max; \
00100 } \
00101 r = (r * opacity + (temp_type)output[0] * transparency) / max; \
00102 g = (g * opacity + (temp_type)output[1] * transparency) / max; \
00103 b = (b * opacity + (temp_type)output[2] * transparency) / max; \
00104 break; \
00105 case TRANSFER_MULTIPLY: \
00106 r = ((temp_type)input1 * output[0]) / max; \
00107 if(chroma_offset) \
00108 { \
00109 g = my_abs((temp_type)input2 - chroma_offset) > my_abs((temp_type)output[1] - chroma_offset) ? input2 : output[1]; \
00110 b = my_abs((temp_type)input3 - chroma_offset) > my_abs((temp_type)output[2] - chroma_offset) ? input3 : output[2]; \
00111 } \
00112 else \
00113 { \
00114 g = (temp_type)input2 * (temp_type)output[1] / max; \
00115 b = (temp_type)input3 * (temp_type)output[2] / max; \
00116 } \
00117 r = (r * opacity + (temp_type)output[0] * transparency) / max; \
00118 g = (g * opacity + (temp_type)output[1] * transparency) / max; \
00119 b = (b * opacity + (temp_type)output[2] * transparency) / max; \
00120 break; \
00121 case TRANSFER_SUBTRACT: \
00122 r = (temp_type)output[0] - (temp_type)input1; \
00123 g = ((temp_type)output[1] - (temp_type)chroma_offset) - \
00124 ((temp_type)input2 - (temp_type)chroma_offset) + \
00125 (temp_type)chroma_offset; \
00126 b = ((temp_type)output[2] - (temp_type)chroma_offset) - \
00127 ((temp_type)input3 - (temp_type)chroma_offset) + \
00128 (temp_type)chroma_offset; \
00129 if(r < 0) r = 0; \
00130 if(g < 0) g = 0; \
00131 if(b < 0) b = 0; \
00132 r = (r * opacity + output[0] * transparency) / max; \
00133 g = (g * opacity + output[1] * transparency) / max; \
00134 b = (b * opacity + output[2] * transparency) / max; \
00135 break; \
00136 case TRANSFER_ADDITION: \
00137 r = (temp_type)input1 + output[0]; \
00138 g = ((temp_type)input2 - chroma_offset) + \
00139 ((temp_type)output[1] - chroma_offset) + \
00140 (temp_type)chroma_offset; \
00141 b = ((temp_type)input3 - chroma_offset) + \
00142 ((temp_type)output[2] - chroma_offset) + \
00143 (temp_type)chroma_offset; \
00144 r = (r * opacity + output[0] * transparency) / max; \
00145 g = (g * opacity + output[1] * transparency) / max; \
00146 b = (b * opacity + output[2] * transparency) / max; \
00147 break; \
00148 case TRANSFER_MAX: \
00149 { \
00150 r = (temp_type)MAX(input1, output[0]); \
00151 temp_type g1 = ((temp_type)input2 - chroma_offset); \
00152 if(g1 < 0) g1 = -g1; \
00153 temp_type g2 = ((temp_type)output[1] - chroma_offset); \
00154 if(g2 < 0) g2 = -g2; \
00155 if(g1 > g2) \
00156 g = input2; \
00157 else \
00158 g = output[1]; \
00159 temp_type b1 = ((temp_type)input3 - chroma_offset); \
00160 if(b1 < 0) b1 = -b1; \
00161 temp_type b2 = ((temp_type)output[2] - chroma_offset); \
00162 if(b2 < 0) b2 = -b2; \
00163 if(b1 > b2) \
00164 b = input3; \
00165 else \
00166 b = output[2]; \
00167 r = (r * opacity + output[0] * transparency) / max; \
00168 g = (g * opacity + output[1] * transparency) / max; \
00169 b = (b * opacity + output[2] * transparency) / max; \
00170 break; \
00171 } \
00172 case TRANSFER_REPLACE: \
00173 r = input1; \
00174 g = input2; \
00175 b = input3; \
00176 break; \
00177 case TRANSFER_NORMAL: \
00178 r = ((temp_type)input1 * opacity + output[0] * transparency) / max; \
00179 g = ((temp_type)input2 * opacity + output[1] * transparency) / max; \
00180 b = ((temp_type)input3 * opacity + output[2] * transparency) / max; \
00181 break; \
00182 } \
00183 \
00184 if(sizeof(type) != 4) \
00185 { \
00186 output[0] = (type)CLIP(r, 0, max); \
00187 output[1] = (type)CLIP(g, 0, max); \
00188 output[2] = (type)CLIP(b, 0, max); \
00189 } \
00190 else \
00191 { \
00192 output[0] = r; \
00193 output[1] = g; \
00194 output[2] = b; \
00195 } \
00196 }
00197
00198
00199
00200
00201
00202
00203 #define BLEND_4(max, temp_type, type, chroma_offset) \
00204 { \
00205 temp_type r, g, b, a; \
00206 temp_type pixel_opacity, pixel_transparency; \
00207 temp_type output1 = output[0]; \
00208 temp_type output2 = output[1]; \
00209 temp_type output3 = output[2]; \
00210 temp_type output4 = output[3]; \
00211 \
00212 pixel_opacity = opacity * input4; \
00213 pixel_transparency = (temp_type)max * max - pixel_opacity; \
00214 \
00215 switch(mode) \
00216 { \
00217 case TRANSFER_DIVIDE: \
00218 r = input1 ? (((temp_type)output1 * max) / input1) : max; \
00219 if(chroma_offset) \
00220 { \
00221 g = my_abs((temp_type)input2 - chroma_offset) > my_abs((temp_type)output2 - chroma_offset) ? input2 : output2; \
00222 b = my_abs((temp_type)input3 - chroma_offset) > my_abs((temp_type)output3 - chroma_offset) ? input3 : output3; \
00223 } \
00224 else \
00225 { \
00226 g = input2 ? (temp_type)output2 * max / (temp_type)input2 : max; \
00227 b = input3 ? (temp_type)output3 * max / (temp_type)input3 : max; \
00228 } \
00229 r = (r * pixel_opacity + (temp_type)output1 * pixel_transparency) / max / max; \
00230 g = (g * pixel_opacity + (temp_type)output2 * pixel_transparency) / max / max; \
00231 b = (b * pixel_opacity + (temp_type)output3 * pixel_transparency) / max / max; \
00232 a = input4 > output4 ? input4 : output4; \
00233 break; \
00234 case TRANSFER_MULTIPLY: \
00235 r = ((temp_type)input1 * output1) / max; \
00236 if(chroma_offset) \
00237 { \
00238 g = my_abs((temp_type)input2 - chroma_offset) > my_abs((temp_type)output2 - chroma_offset) ? input2 : output2; \
00239 b = my_abs((temp_type)input3 - chroma_offset) > my_abs((temp_type)output3 - chroma_offset) ? input3 : output3; \
00240 } \
00241 else \
00242 { \
00243 g = (temp_type)input2 * (temp_type)output2 / max; \
00244 b = (temp_type)input3 * (temp_type)output3 / max; \
00245 } \
00246 r = (r * pixel_opacity + (temp_type)output1 * pixel_transparency) / max / max; \
00247 g = (g * pixel_opacity + (temp_type)output2 * pixel_transparency) / max / max; \
00248 b = (b * pixel_opacity + (temp_type)output3 * pixel_transparency) / max / max; \
00249 a = input4 > output4 ? input4 : output4; \
00250 break; \
00251 case TRANSFER_SUBTRACT: \
00252 r = (temp_type)output1 - input1; \
00253 g = ((temp_type)output2 - chroma_offset) - \
00254 ((temp_type)input2 - (temp_type)chroma_offset) + \
00255 (temp_type)chroma_offset; \
00256 b = ((temp_type)output3 - chroma_offset) - \
00257 ((temp_type)input3 - (temp_type)chroma_offset) + \
00258 (temp_type)chroma_offset; \
00259 if(r < 0) r = 0; \
00260 if(g < 0) g = 0; \
00261 if(b < 0) b = 0; \
00262 r = (r * pixel_opacity + output1 * pixel_transparency) / max / max; \
00263 g = (g * pixel_opacity + output2 * pixel_transparency) / max / max; \
00264 b = (b * pixel_opacity + output3 * pixel_transparency) / max / max; \
00265 a = input4 > output4 ? input4 : output4; \
00266 break; \
00267 case TRANSFER_ADDITION: \
00268 r = (temp_type)input1 + output1; \
00269 g = ((temp_type)input2 - chroma_offset) + \
00270 ((temp_type)output2 - chroma_offset) + \
00271 chroma_offset; \
00272 b = ((temp_type)input3 - chroma_offset) + \
00273 ((temp_type)output3 - chroma_offset) + \
00274 chroma_offset; \
00275 r = (r * pixel_opacity + output1 * pixel_transparency) / max / max; \
00276 g = (g * pixel_opacity + output2 * pixel_transparency) / max / max; \
00277 b = (b * pixel_opacity + output3 * pixel_transparency) / max / max; \
00278 a = input4 > output4 ? input4 : output4; \
00279 break; \
00280 case TRANSFER_MAX: \
00281 { \
00282 r = (temp_type)MAX(input1, output1); \
00283 temp_type g1 = ((temp_type)input2 - chroma_offset); \
00284 if(g1 < 0) g1 = -g1; \
00285 temp_type g2 = ((temp_type)output2 - chroma_offset); \
00286 if(g2 < 0) g2 = -g2; \
00287 if(g1 > g2) \
00288 g = input2; \
00289 else \
00290 g = output2; \
00291 temp_type b1 = ((temp_type)input3 - chroma_offset); \
00292 if(b1 < 0) b1 = -b1; \
00293 temp_type b2 = ((temp_type)output3 - chroma_offset); \
00294 if(b2 < 0) b2 = -b2; \
00295 if(b1 > b2) \
00296 b = input3; \
00297 else \
00298 b = output3; \
00299 r = (r * pixel_opacity + output1 * pixel_transparency) / max / max; \
00300 g = (g * pixel_opacity + output2 * pixel_transparency) / max / max; \
00301 b = (b * pixel_opacity + output3 * pixel_transparency) / max / max; \
00302 a = input4 > output4 ? input4 : output4; \
00303 break; \
00304 } \
00305 case TRANSFER_REPLACE: \
00306 r = input1; \
00307 g = input2; \
00308 b = input3; \
00309 a = input4; \
00310 break; \
00311 case TRANSFER_NORMAL: \
00312 r = (input1 * pixel_opacity + \
00313 output1 * pixel_transparency) / max / max; \
00314 g = ((input2 - chroma_offset) * pixel_opacity + \
00315 (output2 - chroma_offset) * pixel_transparency) \
00316 / max / max + \
00317 chroma_offset; \
00318 b = ((input3 - chroma_offset) * pixel_opacity + \
00319 (output3 - chroma_offset) * pixel_transparency) \
00320 / max / max + \
00321 chroma_offset; \
00322 a = input4 > output4 ? input4 : output4; \
00323 break; \
00324 } \
00325 \
00326 if(sizeof(type) != 4) \
00327 { \
00328 output[0] = (type)CLIP(r, 0, max); \
00329 output[1] = (type)CLIP(g, 0, max); \
00330 output[2] = (type)CLIP(b, 0, max); \
00331 output[3] = (type)a; \
00332 } \
00333 else \
00334 { \
00335 output[0] = r; \
00336 output[1] = g; \
00337 output[2] = b; \
00338 output[3] = a; \
00339 } \
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 int OverlayFrame::overlay(VFrame *output,
00352 VFrame *input,
00353 float in_x1,
00354 float in_y1,
00355 float in_x2,
00356 float in_y2,
00357 float out_x1,
00358 float out_y1,
00359 float out_x2,
00360 float out_y2,
00361 float alpha,
00362 int mode,
00363 int interpolation_type)
00364 {
00365 float w_scale = (out_x2 - out_x1) / (in_x2 - in_x1);
00366 float h_scale = (out_y2 - out_y1) / (in_y2 - in_y1);
00367
00368
00369
00370
00371
00372
00373
00374
00375 if(isnan(in_x1) ||
00376 isnan(in_y1) ||
00377 isnan(in_x2) ||
00378 isnan(in_y2) ||
00379 isnan(out_x1) ||
00380 isnan(out_y1) ||
00381 isnan(out_x2) ||
00382 isnan(out_y2)) return 1;
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 if(in_x1 < 0)
00396 {
00397 out_x1 += -in_x1 * w_scale;
00398 in_x1 = 0;
00399 }
00400 else
00401 if(in_x1 >= input->get_w())
00402 {
00403 out_x1 -= (in_x1 - input->get_w()) * w_scale;
00404 in_x1 = input->get_w();
00405 }
00406
00407 if(in_y1 < 0)
00408 {
00409 out_y1 += -in_y1 * h_scale;
00410 in_y1 = 0;
00411 }
00412 else
00413 if(in_y1 >= input->get_h())
00414 {
00415 out_y1 -= (in_y1 - input->get_h()) * h_scale;
00416 in_y1 = input->get_h();
00417 }
00418
00419 if(in_x2 < 0)
00420 {
00421 out_x2 += -in_x2 * w_scale;
00422 in_x2 = 0;
00423 }
00424 else
00425 if(in_x2 >= input->get_w())
00426 {
00427 out_x2 -= (in_x2 - input->get_w()) * w_scale;
00428 in_x2 = input->get_w();
00429 }
00430
00431 if(in_y2 < 0)
00432 {
00433 out_y2 += -in_y2 * h_scale;
00434 in_y2 = 0;
00435 }
00436 else
00437 if(in_y2 >= input->get_h())
00438 {
00439 out_y2 -= (in_y2 - input->get_h()) * h_scale;
00440 in_y2 = input->get_h();
00441 }
00442
00443 if(out_x1 < 0)
00444 {
00445 in_x1 += -out_x1 / w_scale;
00446 out_x1 = 0;
00447 }
00448 else
00449 if(out_x1 >= output->get_w())
00450 {
00451 in_x1 -= (out_x1 - output->get_w()) / w_scale;
00452 out_x1 = output->get_w();
00453 }
00454
00455 if(out_y1 < 0)
00456 {
00457 in_y1 += -out_y1 / h_scale;
00458 out_y1 = 0;
00459 }
00460 else
00461 if(out_y1 >= output->get_h())
00462 {
00463 in_y1 -= (out_y1 - output->get_h()) / h_scale;
00464 out_y1 = output->get_h();
00465 }
00466
00467 if(out_x2 < 0)
00468 {
00469 in_x2 += -out_x2 / w_scale;
00470 out_x2 = 0;
00471 }
00472 else
00473 if(out_x2 >= output->get_w())
00474 {
00475 in_x2 -= (out_x2 - output->get_w()) / w_scale;
00476 out_x2 = output->get_w();
00477 }
00478
00479 if(out_y2 < 0)
00480 {
00481 in_y2 += -out_y2 / h_scale;
00482 out_y2 = 0;
00483 }
00484 else
00485 if(out_y2 >= output->get_h())
00486 {
00487 in_y2 -= (out_y2 - output->get_h()) / h_scale;
00488 out_y2 = output->get_h();
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 float in_w = in_x2 - in_x1;
00501 float in_h = in_y2 - in_y1;
00502 float out_w = out_x2 - out_x1;
00503 float out_h = out_y2 - out_y1;
00504
00505 VFrame *translation_input = input;
00506
00507
00508 if(in_w <= 0 || in_h <= 0 || out_w <= 0 || out_h <= 0) return 0;
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527 if(interpolation_type != NEAREST_NEIGHBOR &&
00528 (!EQUIV(w_scale, 1) || !EQUIV(h_scale, 1)))
00529 {
00530
00531 float in_x1_float = in_x1;
00532 float in_y1_float = in_y1;
00533 float in_x2_float = MIN(in_x2, input->get_w());
00534 float in_y2_float = MIN(in_y2, input->get_h());
00535 int out_x1_int = (int)out_x1;
00536 int out_y1_int = (int)out_y1;
00537 int out_x2_int = MIN((int)ceil(out_x2), output->get_w());
00538 int out_y2_int = MIN((int)ceil(out_y2), output->get_h());
00539
00540
00541 int temp_w = (out_x2_int - out_x1_int);
00542 int temp_h = (out_y2_int - out_y1_int);
00543 VFrame *scale_output;
00544
00545
00546
00547 #define NO_TRANSLATION1 \
00548 (EQUIV(in_x1, 0) && \
00549 EQUIV(in_y1, 0) && \
00550 EQUIV(out_x1, 0) && \
00551 EQUIV(out_y1, 0) && \
00552 EQUIV(in_x2, in_x2_float) && \
00553 EQUIV(in_y2, in_y2_float) && \
00554 EQUIV(out_x2, temp_w) && \
00555 EQUIV(out_y2, temp_h))
00556
00557
00558 #define NO_BLEND \
00559 (EQUIV(alpha, 1) && \
00560 (mode == TRANSFER_REPLACE || \
00561 (mode == TRANSFER_NORMAL && cmodel_components(input->get_color_model()) == 3)))
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572 if(NO_TRANSLATION1 &&
00573 NO_BLEND)
00574 {
00575
00576
00577 scale_output = output;
00578 translation_input = 0;
00579 }
00580 else
00581
00582
00583 {
00584 if(temp_frame &&
00585 (temp_frame->get_w() != temp_w ||
00586 temp_frame->get_h() != temp_h))
00587 {
00588 delete temp_frame;
00589 temp_frame = 0;
00590 }
00591
00592 if(!temp_frame)
00593 {
00594 temp_frame = new VFrame(0,
00595 temp_w,
00596 temp_h,
00597 input->get_color_model(),
00598 -1);
00599 }
00600
00601
00602
00603 temp_frame->clear_frame();
00604
00605
00606
00607 scale_output = temp_frame;
00608 translation_input = scale_output;
00609
00610
00611 in_x1 = 0;
00612 in_y1 = 0;
00613 in_x2 = temp_w;
00614 in_y2 = temp_h;
00615 }
00616
00617
00618
00619
00620
00621
00622 if(!scale_engine) scale_engine = new ScaleEngine(this, cpus);
00623 scale_engine->scale_output = scale_output;
00624 scale_engine->scale_input = input;
00625 scale_engine->w_scale = w_scale;
00626 scale_engine->h_scale = h_scale;
00627 scale_engine->in_x1_float = in_x1_float;
00628 scale_engine->in_y1_float = in_y1_float;
00629 scale_engine->out_w_int = temp_w;
00630 scale_engine->out_h_int = temp_h;
00631 scale_engine->interpolation_type = interpolation_type;
00632
00633
00634
00635 scale_engine->process_packages();
00636
00637
00638
00639
00640 }
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656 #define NO_TRANSLATION2 \
00657 (EQUIV(in_x1, 0) && \
00658 EQUIV(in_y1, 0) && \
00659 EQUIV(in_x2, translation_input->get_w()) && \
00660 EQUIV(in_y2, translation_input->get_h()) && \
00661 EQUIV(out_x1, 0) && \
00662 EQUIV(out_y1, 0) && \
00663 EQUIV(out_x2, output->get_w()) && \
00664 EQUIV(out_y2, output->get_h())) \
00665
00666 #define NO_SCALE \
00667 (EQUIV(out_x2 - out_x1, in_x2 - in_x1) && \
00668 EQUIV(out_y2 - out_y1, in_y2 - in_y1))
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678 if(translation_input)
00679 {
00680
00681 if( NO_TRANSLATION2 &&
00682 NO_SCALE &&
00683 NO_BLEND)
00684 {
00685
00686 output->copy_from(translation_input);
00687 }
00688 else
00689
00690 if( NO_TRANSLATION2 &&
00691 NO_SCALE)
00692 {
00693 if(!blend_engine) blend_engine = new BlendEngine(this, cpus);
00694
00695
00696 blend_engine->output = output;
00697 blend_engine->input = translation_input;
00698 blend_engine->alpha = alpha;
00699 blend_engine->mode = mode;
00700
00701 blend_engine->process_packages();
00702 }
00703 else
00704
00705
00706 if(interpolation_type == NEAREST_NEIGHBOR ||
00707 EQUIV(in_x1, (int)in_x1) &&
00708 EQUIV(in_y1, (int)in_y1) &&
00709 EQUIV(in_x2, (int)in_x2) &&
00710 EQUIV(in_y2, (int)in_y2) &&
00711
00712 EQUIV(out_x1, (int)out_x1) &&
00713 EQUIV(out_y1, (int)out_y1) &&
00714 EQUIV(out_x2, (int)out_x2) &&
00715 EQUIV(out_y2, (int)out_y2))
00716 {
00717
00718 if(!scaletranslate_engine) scaletranslate_engine =
00719 new ScaleTranslateEngine(this, cpus);
00720
00721
00722 scaletranslate_engine->output = output;
00723 scaletranslate_engine->input = translation_input;
00724
00725 scaletranslate_engine->in_x1 = in_x1;
00726 scaletranslate_engine->in_y1 = in_y1;
00727 scaletranslate_engine->in_x2 = in_x2;
00728 scaletranslate_engine->in_y2 = in_y2;
00729 scaletranslate_engine->out_x1 = (int)out_x1;
00730 scaletranslate_engine->out_y1 = (int)out_y1;
00731 scaletranslate_engine->out_x2 = (int)out_x1 + (int)(out_x2 - out_x1);
00732 scaletranslate_engine->out_y2 = (int)out_y1 + (int)(out_y2 - out_y1);
00733 scaletranslate_engine->alpha = alpha;
00734 scaletranslate_engine->mode = mode;
00735
00736 scaletranslate_engine->process_packages();
00737 }
00738 else
00739
00740 {
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 if(!translate_engine) translate_engine = new TranslateEngine(this, cpus);
00754 translate_engine->translate_output = output;
00755 translate_engine->translate_input = translation_input;
00756 translate_engine->translate_in_x1 = in_x1;
00757 translate_engine->translate_in_y1 = in_y1;
00758 translate_engine->translate_in_x2 = in_x2;
00759 translate_engine->translate_in_y2 = in_y2;
00760 translate_engine->translate_out_x1 = out_x1;
00761 translate_engine->translate_out_y1 = out_y1;
00762 translate_engine->translate_out_x2 = out_x2;
00763 translate_engine->translate_out_y2 = out_y2;
00764 translate_engine->translate_alpha = alpha;
00765 translate_engine->translate_mode = mode;
00766
00767
00768
00769 translate_engine->process_packages();
00770
00771 }
00772 }
00773
00774
00775 return 0;
00776 }
00777
00778
00779
00780
00781
00782
00783
00784 ScalePackage::ScalePackage()
00785 {
00786 }
00787
00788
00789
00790
00791 ScaleUnit::ScaleUnit(ScaleEngine *server, OverlayFrame *overlay)
00792 : LoadClient(server)
00793 {
00794 this->overlay = overlay;
00795 this->engine = server;
00796 }
00797
00798 ScaleUnit::~ScaleUnit()
00799 {
00800 }
00801
00802
00803
00804 void ScaleUnit::tabulate_reduction(bilinear_table_t* &table,
00805 float scale,
00806 int in_pixel1,
00807 int out_total,
00808 int in_total)
00809 {
00810 table = new bilinear_table_t[out_total];
00811 bzero(table, sizeof(bilinear_table_t) * out_total);
00812
00813 for(int i = 0; i < out_total; i++)
00814 {
00815 float out_start = i;
00816 float in_start = out_start * scale;
00817 float out_end = i + 1;
00818 float in_end = out_end * scale;
00819 bilinear_table_t *entry = table + i;
00820
00821
00822
00823 entry->input_fraction1 = (floor(in_start + 1) - in_start) ;
00824 entry->input_fraction2 = 1.0 ;
00825 entry->input_fraction3 = (in_end - floor(in_end)) ;
00826
00827 if(in_end >= in_total - in_pixel1)
00828 {
00829 in_end = in_total - in_pixel1 - 1;
00830
00831 int difference = (int)in_end - (int)in_start - 1;
00832 if(difference < 0) difference = 0;
00833 entry->input_fraction3 = 1.0 -
00834 entry->input_fraction1 -
00835 entry->input_fraction2 * difference;
00836 }
00837
00838
00839 entry->input_pixel1 = (int)in_start;
00840 entry->input_pixel2 = (int)in_end;
00841
00842
00843 if(entry->input_pixel2 > entry->input_pixel1 + 1)
00844 {
00845 float total = entry->input_fraction1 +
00846 entry->input_fraction2 *
00847 (entry->input_pixel2 - entry->input_pixel1 - 1) +
00848 entry->input_fraction3;
00849 entry->input_fraction1 /= total;
00850 entry->input_fraction2 /= total;
00851 entry->input_fraction3 /= total;
00852 }
00853 else
00854 {
00855 float total = entry->input_fraction1 +
00856 entry->input_fraction3;
00857 entry->input_fraction1 /= total;
00858 entry->input_fraction3 /= total;
00859 }
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875 if(entry->input_pixel1 > entry->input_pixel2)
00876 {
00877 entry->input_pixel1 = entry->input_pixel2;
00878 entry->input_fraction1 = 0;
00879 }
00880
00881
00882
00883 entry->total_fraction =
00884 entry->input_fraction1 +
00885 entry->input_fraction2 * (entry->input_pixel2 - entry->input_pixel1 - 1) +
00886 entry->input_fraction3;
00887 entry->input_pixel1 += in_pixel1;
00888 entry->input_pixel2 += in_pixel1;
00889 }
00890 }
00891
00892 void ScaleUnit::tabulate_enlarge(bilinear_table_t* &table,
00893 float scale,
00894 float in_pixel1,
00895 int out_total,
00896 int in_total)
00897 {
00898 table = new bilinear_table_t[out_total];
00899 bzero(table, sizeof(bilinear_table_t) * out_total);
00900
00901 for(int i = 0; i < out_total; i++)
00902 {
00903 bilinear_table_t *entry = table + i;
00904 float in_pixel = i * scale + in_pixel1;
00905 entry->input_pixel1 = (int)floor(in_pixel);
00906 entry->input_pixel2 = entry->input_pixel1 + 1;
00907
00908 if(in_pixel - in_pixel1 <= in_total)
00909 {
00910 entry->input_fraction3 = in_pixel - entry->input_pixel1;
00911 }
00912 else
00913 {
00914 entry->input_fraction3 = 0;
00915 entry->input_pixel2 = 0;
00916 }
00917
00918 if(in_pixel - in_pixel1 >= 0)
00919 {
00920 entry->input_fraction1 = entry->input_pixel2 - in_pixel;
00921 }
00922 else
00923 {
00924 entry->input_fraction1 = 0;
00925 entry->input_pixel1 = (int)in_pixel1;
00926 }
00927
00928 if(entry->input_pixel2 >= in_total)
00929 {
00930 entry->input_pixel2 = entry->input_pixel1;
00931 entry->input_fraction3 = 1.0 - entry->input_fraction1;
00932 }
00933
00934 entry->total_fraction =
00935 entry->input_fraction1 +
00936 entry->input_fraction3;
00937
00938
00939
00940
00941
00942
00943
00944 }
00945 }
00946
00947 void ScaleUnit::dump_bilinear(bilinear_table_t *table, int total)
00948 {
00949 printf("ScaleUnit::dump_bilinear\n");
00950 for(int i = 0; i < total; i++)
00951 {
00952 printf("out=%d inpixel1=%d inpixel2=%d infrac1=%f infrac2=%f infrac3=%f total=%f\n",
00953 i,
00954 table[i].input_pixel1,
00955 table[i].input_pixel2,
00956 table[i].input_fraction1,
00957 table[i].input_fraction2,
00958 table[i].input_fraction3,
00959 table[i].total_fraction);
00960 }
00961 }
00962
00963 #define PIXEL_REDUCE_MACRO(type, components, row) \
00964 { \
00965 type *input_row = &in_rows[row][x_entry->input_pixel1 * components]; \
00966 type *input_end = &in_rows[row][x_entry->input_pixel2 * components]; \
00967 \
00968 \
00969 temp_f1 += input_scale1 * input_row[0]; \
00970 temp_f2 += input_scale1 * input_row[1]; \
00971 temp_f3 += input_scale1 * input_row[2]; \
00972 if(components == 4) temp_f4 += input_scale1 * input_row[3]; \
00973 \
00974 \
00975 \
00976 { \
00977 temp_f1 += input_scale3 * input_end[0]; \
00978 temp_f2 += input_scale3 * input_end[1]; \
00979 temp_f3 += input_scale3 * input_end[2]; \
00980 if(components == 4) temp_f4 += input_scale3 * input_end[3]; \
00981 } \
00982 \
00983 \
00984 for(input_row += components; input_row < input_end; input_row += components) \
00985 { \
00986 temp_f1 += input_scale2 * input_row[0]; \
00987 temp_f2 += input_scale2 * input_row[1]; \
00988 temp_f3 += input_scale2 * input_row[2]; \
00989 if(components == 4) temp_f4 += input_scale2 * input_row[3]; \
00990 } \
00991 }
00992
00993
00994
00995 #define BILINEAR_REDUCE(max, type, components) \
00996 { \
00997 bilinear_table_t *x_table, *y_table; \
00998 int out_h = pkg->out_row2 - pkg->out_row1; \
00999 type **in_rows = (type**)input->get_rows(); \
01000 type **out_rows = (type**)output->get_rows(); \
01001 \
01002 if(scale_w < 1) \
01003 tabulate_reduction(x_table, \
01004 1.0 / scale_w, \
01005 (int)in_x1_float, \
01006 out_w_int, \
01007 input->get_w()); \
01008 else \
01009 tabulate_enlarge(x_table, \
01010 1.0 / scale_w, \
01011 in_x1_float, \
01012 out_w_int, \
01013 input->get_w()); \
01014 \
01015 if(scale_h < 1) \
01016 tabulate_reduction(y_table, \
01017 1.0 / scale_h, \
01018 (int)in_y1_float, \
01019 out_h_int, \
01020 input->get_h()); \
01021 else \
01022 tabulate_enlarge(y_table, \
01023 1.0 / scale_h, \
01024 in_y1_float, \
01025 out_h_int, \
01026 input->get_h()); \
01027 \
01028 \
01029 for(int i = 0; i < out_h; i++) \
01030 { \
01031 type *out_row = out_rows[i + pkg->out_row1]; \
01032 bilinear_table_t *y_entry = &y_table[i + pkg->out_row1]; \
01033 \
01034 \
01035 \
01036 \
01037 \
01038 \
01039 \
01040 \
01041 for(int j = 0; j < out_w_int; j++) \
01042 { \
01043 bilinear_table_t *x_entry = &x_table[j]; \
01044 \
01045 float temp_f1; \
01046 float temp_f2; \
01047 float temp_f3; \
01048 float temp_f4; \
01049 if(sizeof(type) != 4) \
01050 temp_f1 = temp_f2 = temp_f3 = temp_f4 = .5; \
01051 else \
01052 temp_f1 = temp_f2 = temp_f3 = temp_f4 = 0; \
01053 \
01054 \
01055 float input_scale1 = y_entry->input_fraction1 * x_entry->input_fraction1; \
01056 float input_scale2 = y_entry->input_fraction1 * x_entry->input_fraction2; \
01057 float input_scale3 = y_entry->input_fraction1 * x_entry->input_fraction3; \
01058 PIXEL_REDUCE_MACRO(type, components, y_entry->input_pixel1) \
01059 \
01060 \
01061 if(out_h) \
01062 { \
01063 input_scale1 = y_entry->input_fraction3 * x_entry->input_fraction1; \
01064 input_scale2 = y_entry->input_fraction3 * x_entry->input_fraction2; \
01065 input_scale3 = y_entry->input_fraction3 * x_entry->input_fraction3; \
01066 PIXEL_REDUCE_MACRO(type, components, y_entry->input_pixel2) \
01067 \
01068 \
01069 if(out_h > 1) \
01070 { \
01071 input_scale1 = y_entry->input_fraction2 * x_entry->input_fraction1; \
01072 input_scale2 = y_entry->input_fraction2 * x_entry->input_fraction2; \
01073 input_scale3 = y_entry->input_fraction2 * x_entry->input_fraction3; \
01074 for(int k = y_entry->input_pixel1 + 1; \
01075 k < y_entry->input_pixel2; \
01076 k++) \
01077 { \
01078 PIXEL_REDUCE_MACRO(type, components, k) \
01079 } \
01080 } \
01081 } \
01082 \
01083 \
01084 if(max != 1.0) \
01085 { \
01086 if(temp_f1 > max) temp_f1 = max; \
01087 if(temp_f2 > max) temp_f2 = max; \
01088 if(temp_f3 > max) temp_f3 = max; \
01089 if(components == 4) if(temp_f4 > max) temp_f4 = max; \
01090 } \
01091 \
01092 out_row[j * components ] = (type)temp_f1; \
01093 out_row[j * components + 1] = (type)temp_f2; \
01094 out_row[j * components + 2] = (type)temp_f3; \
01095 if(components == 4) out_row[j * components + 3] = (type)temp_f4; \
01096 } \
01097 \
01098 } \
01099 \
01100 delete [] x_table; \
01101 delete [] y_table; \
01102 }
01103
01104
01105
01106
01107 #define BILINEAR_ENLARGE(max, type, components) \
01108 { \
01109 \
01110 float k_y = 1.0 / scale_h; \
01111 float k_x = 1.0 / scale_w; \
01112 type **in_rows = (type**)input->get_rows(); \
01113 type **out_rows = (type**)output->get_rows(); \
01114 int out_h = pkg->out_row2 - pkg->out_row1; \
01115 int in_h_int = input->get_h(); \
01116 int in_w_int = input->get_w(); \
01117 int *table_int_x1, *table_int_y1; \
01118 int *table_int_x2, *table_int_y2; \
01119 float *table_frac_x_f, *table_antifrac_x_f, *table_frac_y_f, *table_antifrac_y_f; \
01120 int *table_frac_x_i, *table_antifrac_x_i, *table_frac_y_i, *table_antifrac_y_i; \
01121 \
01122 tabulate_blinear_f(table_int_x1, \
01123 table_int_x2, \
01124 table_frac_x_f, \
01125 table_antifrac_x_f, \
01126 k_x, \
01127 0, \
01128 out_w_int, \
01129 in_x1_float, \
01130 in_w_int); \
01131 tabulate_blinear_f(table_int_y1, \
01132 table_int_y2, \
01133 table_frac_y_f, \
01134 table_antifrac_y_f, \
01135 k_y, \
01136 pkg->out_row1, \
01137 pkg->out_row2, \
01138 in_y1_float, \
01139 in_h_int); \
01140 \
01141 for(int i = 0; i < out_h; i++) \
01142 { \
01143 int i_y1 = table_int_y1[i]; \
01144 int i_y2 = table_int_y2[i]; \
01145 float a_f; \
01146 float anti_a_f; \
01147 uint64_t a_i; \
01148 uint64_t anti_a_i; \
01149 a_f = table_frac_y_f[i]; \
01150 anti_a_f = table_antifrac_y_f[i]; \
01151 type *in_row1 = in_rows[i_y1]; \
01152 type *in_row2 = in_rows[i_y2]; \
01153 type *out_row = out_rows[i + pkg->out_row1]; \
01154 \
01155 for(int j = 0; j < out_w_int; j++) \
01156 { \
01157 int i_x1 = table_int_x1[j]; \
01158 int i_x2 = table_int_x2[j]; \
01159 float output1r, output1g, output1b, output1a; \
01160 float output2r, output2g, output2b, output2a; \
01161 float output3r, output3g, output3b, output3a; \
01162 float output4r, output4g, output4b, output4a; \
01163 float b_f; \
01164 float anti_b_f; \
01165 b_f = table_frac_x_f[j]; \
01166 anti_b_f = table_antifrac_x_f[j]; \
01167 \
01168 output1r = in_row1[i_x1 * components]; \
01169 output1g = in_row1[i_x1 * components + 1]; \
01170 output1b = in_row1[i_x1 * components + 2]; \
01171 if(components == 4) output1a = in_row1[i_x1 * components + 3]; \
01172 \
01173 output2r = in_row1[i_x2 * components]; \
01174 output2g = in_row1[i_x2 * components + 1]; \
01175 output2b = in_row1[i_x2 * components + 2]; \
01176 if(components == 4) output2a = in_row1[i_x2 * components + 3]; \
01177 \
01178 output3r = in_row2[i_x1 * components]; \
01179 output3g = in_row2[i_x1 * components + 1]; \
01180 output3b = in_row2[i_x1 * components + 2]; \
01181 if(components == 4) output3a = in_row2[i_x1 * components + 3]; \
01182 \
01183 output4r = in_row2[i_x2 * components]; \
01184 output4g = in_row2[i_x2 * components + 1]; \
01185 output4b = in_row2[i_x2 * components + 2]; \
01186 if(components == 4) output4a = in_row2[i_x2 * components + 3]; \
01187 \
01188 out_row[j * components] = \
01189 (type)(anti_a_f * (anti_b_f * output1r + \
01190 b_f * output2r) + \
01191 a_f * (anti_b_f * output3r + \
01192 b_f * output4r)); \
01193 out_row[j * components + 1] = \
01194 (type)(anti_a_f * (anti_b_f * output1g + \
01195 b_f * output2g) + \
01196 a_f * ((anti_b_f * output3g) + \
01197 b_f * output4g)); \
01198 out_row[j * components + 2] = \
01199 (type)(anti_a_f * ((anti_b_f * output1b) + \
01200 (b_f * output2b)) + \
01201 a_f * ((anti_b_f * output3b) + \
01202 b_f * output4b)); \
01203 if(components == 4) \
01204 out_row[j * components + 3] = \
01205 (type)(anti_a_f * ((anti_b_f * output1a) + \
01206 (b_f * output2a)) + \
01207 a_f * ((anti_b_f * output3a) + \
01208 b_f * output4a)); \
01209 } \
01210 } \
01211 \
01212 \
01213 delete [] table_int_x1; \
01214 delete [] table_int_x2; \
01215 delete [] table_int_y1; \
01216 delete [] table_int_y2; \
01217 delete [] table_frac_x_f; \
01218 delete [] table_antifrac_x_f; \
01219 delete [] table_frac_y_f; \
01220 delete [] table_antifrac_y_f; \
01221 \
01222 \
01223 }
01224
01225
01226 #define BICUBIC(max, type, components) \
01227 { \
01228 float k_y = 1.0 / scale_h; \
01229 float k_x = 1.0 / scale_w; \
01230 type **in_rows = (type**)input->get_rows(); \
01231 type **out_rows = (type**)output->get_rows(); \
01232 float *bspline_x_f, *bspline_y_f; \
01233 int *bspline_x_i, *bspline_y_i; \
01234 int *in_x_table, *in_y_table; \
01235 int in_h_int = input->get_h(); \
01236 int in_w_int = input->get_w(); \
01237 \
01238 tabulate_bcubic_f(bspline_x_f, \
01239 in_x_table, \
01240 k_x, \
01241 in_x1_float, \
01242 out_w_int, \
01243 in_w_int, \
01244 -1); \
01245 \
01246 tabulate_bcubic_f(bspline_y_f, \
01247 in_y_table, \
01248 k_y, \
01249 in_y1_float, \
01250 out_h_int, \
01251 in_h_int, \
01252 1); \
01253 \
01254 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
01255 { \
01256 for(int j = 0; j < out_w_int; j++) \
01257 { \
01258 int i_x = (int)(k_x * j); \
01259 float output1_f, output2_f, output3_f, output4_f; \
01260 uint64_t output1_i, output2_i, output3_i, output4_i; \
01261 output1_f = 0; \
01262 output2_f = 0; \
01263 output3_f = 0; \
01264 if(components == 4) \
01265 output4_f = 0; \
01266 int table_y = i * 4; \
01267 \
01268 \
01269 for(int m = -1; m < 3; m++) \
01270 { \
01271 float r1_f; \
01272 uint64_t r1_i; \
01273 r1_f = bspline_y_f[table_y]; \
01274 int y = in_y_table[table_y]; \
01275 int table_x = j * 4; \
01276 \
01277 for(int n = -1; n < 3; n++) \
01278 { \
01279 float r2_f; \
01280 uint64_t r2_i; \
01281 r2_f = bspline_x_f[table_x]; \
01282 int x = in_x_table[table_x]; \
01283 float r_square_f; \
01284 uint64_t r_square_i; \
01285 r_square_f = r1_f * r2_f; \
01286 output1_f += r_square_f * in_rows[y][x * components]; \
01287 output2_f += r_square_f * in_rows[y][x * components + 1]; \
01288 output3_f += r_square_f * in_rows[y][x * components + 2]; \
01289 if(components == 4) \
01290 output4_f += r_square_f * in_rows[y][x * components + 3]; \
01291 \
01292 table_x++; \
01293 } \
01294 table_y++; \
01295 } \
01296 \
01297 \
01298 out_rows[i][j * components] = (type)output1_f; \
01299 out_rows[i][j * components + 1] = (type)output2_f; \
01300 out_rows[i][j * components + 2] = (type)output3_f; \
01301 if(components == 4) \
01302 out_rows[i][j * components + 3] = (type)output4_f; \
01303 \
01304 } \
01305 } \
01306 \
01307 delete [] bspline_x_f; \
01308 delete [] bspline_y_f; \
01309 delete [] in_x_table; \
01310 delete [] in_y_table; \
01311 }
01312
01313
01314
01315
01316
01317 #define CUBE(x) ((x) * (x) * (x))
01318
01319 float ScaleUnit::cubic_bspline(float x)
01320 {
01321 float a, b, c, d;
01322
01323 if((x + 2.0F) <= 0.0F)
01324 {
01325 a = 0.0F;
01326 }
01327 else
01328 {
01329 a = CUBE(x + 2.0F);
01330 }
01331
01332
01333 if((x + 1.0F) <= 0.0F)
01334 {
01335 b = 0.0F;
01336 }
01337 else
01338 {
01339 b = CUBE(x + 1.0F);
01340 }
01341
01342 if(x <= 0)
01343 {
01344 c = 0.0F;
01345 }
01346 else
01347 {
01348 c = CUBE(x);
01349 }
01350
01351 if((x - 1.0F) <= 0.0F)
01352 {
01353 d = 0.0F;
01354 }
01355 else
01356 {
01357 d = CUBE(x - 1.0F);
01358 }
01359
01360
01361 return (a - (4.0F * b) + (6.0F * c) - (4.0F * d)) / 6.0;
01362 }
01363
01364
01365 void ScaleUnit::tabulate_bcubic_f(float* &coef_table,
01366 int* &coord_table,
01367 float scale,
01368 float start,
01369 int pixels,
01370 int total_pixels,
01371 float coefficient)
01372 {
01373 coef_table = new float[pixels * 4];
01374 coord_table = new int[pixels * 4];
01375 for(int i = 0, j = 0; i < pixels; i++)
01376 {
01377 float f_x = (float)i * scale + start;
01378 float a = f_x - floor(f_x);
01379
01380 for(float m = -1; m < 3; m++)
01381 {
01382 coef_table[j] = cubic_bspline(coefficient * (m - a));
01383 coord_table[j] = (int)(f_x + m);
01384 CLAMP(coord_table[j], 0, total_pixels - 1);
01385 j++;
01386 }
01387
01388 }
01389 }
01390
01391 void ScaleUnit::tabulate_bcubic_i(int* &coef_table,
01392 int* &coord_table,
01393 float scale,
01394 int start,
01395 int pixels,
01396 int total_pixels,
01397 float coefficient)
01398 {
01399 coef_table = new int[pixels * 4];
01400 coord_table = new int[pixels * 4];
01401 for(int i = 0, j = 0; i < pixels; i++)
01402 {
01403 float f_x = (float)i * scale + start;
01404 float a = f_x - floor(f_x);
01405
01406 for(float m = -1; m < 3; m++)
01407 {
01408 coef_table[j] = (int)(cubic_bspline(coefficient * (m - a)) * 0x10000);
01409 coord_table[j] = (int)(f_x + m);
01410 CLAMP(coord_table[j], 0, total_pixels - 1);
01411 j++;
01412 }
01413
01414 }
01415 }
01416
01417 void ScaleUnit::tabulate_blinear_f(int* &table_int1,
01418 int* &table_int2,
01419 float* &table_frac,
01420 float* &table_antifrac,
01421 float scale,
01422 int pixel1,
01423 int pixel2,
01424 float start,
01425 int total_pixels)
01426 {
01427 table_int1 = new int[pixel2 - pixel1];
01428 table_int2 = new int[pixel2 - pixel1];
01429 table_frac = new float[pixel2 - pixel1];
01430 table_antifrac = new float[pixel2 - pixel1];
01431
01432 for(int i = pixel1, j = 0; i < pixel2; i++, j++)
01433 {
01434 float f_x = (float)i * scale + start;
01435 int i_x = (int)floor(f_x);
01436 float a = (f_x - floor(f_x));
01437
01438 table_int1[j] = i_x;
01439 table_int2[j] = i_x + 1;
01440 CLAMP(table_int1[j], 0, total_pixels - 1);
01441 CLAMP(table_int2[j], 0, total_pixels - 1);
01442 table_frac[j] = a;
01443 table_antifrac[j] = 1.0F - a;
01444
01445 }
01446 }
01447
01448 void ScaleUnit::tabulate_blinear_i(int* &table_int1,
01449 int* &table_int2,
01450 int* &table_frac,
01451 int* &table_antifrac,
01452 float scale,
01453 int pixel1,
01454 int pixel2,
01455 float start,
01456 int total_pixels)
01457 {
01458 table_int1 = new int[pixel2 - pixel1];
01459 table_int2 = new int[pixel2 - pixel1];
01460 table_frac = new int[pixel2 - pixel1];
01461 table_antifrac = new int[pixel2 - pixel1];
01462
01463 for(int i = pixel1, j = 0; i < pixel2; i++, j++)
01464 {
01465 double f_x = (float)i * scale + start;
01466 int i_x = (int)floor(f_x);
01467 float a = (f_x - floor(f_x));
01468
01469 table_int1[j] = i_x;
01470 table_int2[j] = i_x + 1;
01471 CLAMP(table_int1[j], 0, total_pixels - 1);
01472 CLAMP(table_int2[j], 0, total_pixels - 1);
01473 table_frac[j] = (int)(a * 0xffff);
01474 table_antifrac[j] = (int)((1.0F - a) * 0x10000);
01475
01476 }
01477 }
01478
01479 void ScaleUnit::process_package(LoadPackage *package)
01480 {
01481 ScalePackage *pkg = (ScalePackage*)package;
01482
01483
01484
01485 VFrame *output = engine->scale_output;
01486 VFrame *input = engine->scale_input;
01487 float scale_w = engine->w_scale;
01488 float scale_h = engine->h_scale;
01489 float in_x1_float = engine->in_x1_float;
01490 float in_y1_float = engine->in_y1_float;
01491 int out_h_int = engine->out_h_int;
01492 int out_w_int = engine->out_w_int;
01493 int do_yuv =
01494 (input->get_color_model() == BC_YUV888 ||
01495 input->get_color_model() == BC_YUVA8888 ||
01496 input->get_color_model() == BC_YUV161616 ||
01497 input->get_color_model() == BC_YUVA16161616);
01498
01499
01500 if(engine->interpolation_type == CUBIC_CUBIC ||
01501 (engine->interpolation_type == CUBIC_LINEAR
01502 && engine->w_scale > 1 &&
01503 engine->h_scale > 1))
01504 {
01505 switch(engine->scale_input->get_color_model())
01506 {
01507 case BC_RGB_FLOAT:
01508 BICUBIC(1.0, float, 3);
01509 break;
01510
01511 case BC_RGBA_FLOAT:
01512 BICUBIC(1.0, float, 4);
01513 break;
01514
01515 case BC_RGB888:
01516 case BC_YUV888:
01517 BICUBIC(0xff, unsigned char, 3);
01518 break;
01519
01520 case BC_RGBA8888:
01521 case BC_YUVA8888:
01522 BICUBIC(0xff, unsigned char, 4);
01523 break;
01524
01525 case BC_RGB161616:
01526 case BC_YUV161616:
01527 BICUBIC(0xffff, uint16_t, 3);
01528 break;
01529
01530 case BC_RGBA16161616:
01531 case BC_YUVA16161616:
01532 BICUBIC(0xffff, uint16_t, 4);
01533 break;
01534 }
01535 }
01536 else
01537
01538 if(engine->w_scale > 1 &&
01539 engine->h_scale > 1)
01540 {
01541 switch(engine->scale_input->get_color_model())
01542 {
01543 case BC_RGB_FLOAT:
01544 BILINEAR_ENLARGE(1.0, float, 3);
01545 break;
01546
01547 case BC_RGBA_FLOAT:
01548 BILINEAR_ENLARGE(1.0, float, 4);
01549 break;
01550
01551 case BC_RGB888:
01552 case BC_YUV888:
01553 BILINEAR_ENLARGE(0xff, unsigned char, 3);
01554 break;
01555
01556 case BC_RGBA8888:
01557 case BC_YUVA8888:
01558 BILINEAR_ENLARGE(0xff, unsigned char, 4);
01559 break;
01560
01561 case BC_RGB161616:
01562 case BC_YUV161616:
01563 BILINEAR_ENLARGE(0xffff, uint16_t, 3);
01564 break;
01565
01566 case BC_RGBA16161616:
01567 case BC_YUVA16161616:
01568 BILINEAR_ENLARGE(0xffff, uint16_t, 4);
01569 break;
01570 }
01571 }
01572 else
01573
01574 {
01575 switch(engine->scale_input->get_color_model())
01576 {
01577 case BC_RGB_FLOAT:
01578 BILINEAR_REDUCE(1.0, float, 3);
01579 break;
01580 case BC_RGBA_FLOAT:
01581 BILINEAR_REDUCE(1.0, float, 4);
01582 break;
01583 case BC_RGB888:
01584 case BC_YUV888:
01585 BILINEAR_REDUCE(0xff, unsigned char, 3);
01586 break;
01587
01588 case BC_RGBA8888:
01589 case BC_YUVA8888:
01590 BILINEAR_REDUCE(0xff, unsigned char, 4);
01591 break;
01592
01593 case BC_RGB161616:
01594 case BC_YUV161616:
01595 BILINEAR_REDUCE(0xffff, uint16_t, 3);
01596 break;
01597
01598 case BC_RGBA16161616:
01599 case BC_YUVA16161616:
01600 BILINEAR_REDUCE(0xffff, uint16_t, 4);
01601 break;
01602 }
01603 }
01604
01605
01606 }
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620 ScaleEngine::ScaleEngine(OverlayFrame *overlay, int cpus)
01621 : LoadServer(cpus, cpus)
01622 {
01623 this->overlay = overlay;
01624 }
01625
01626 ScaleEngine::~ScaleEngine()
01627 {
01628 }
01629
01630 void ScaleEngine::init_packages()
01631 {
01632 for(int i = 0; i < get_total_packages(); i++)
01633 {
01634 ScalePackage *package = (ScalePackage*)get_package(i);
01635 package->out_row1 = out_h_int / get_total_packages() * i;
01636 package->out_row2 = package->out_row1 + out_h_int / get_total_packages();
01637
01638 if(i >= get_total_packages() - 1)
01639 package->out_row2 = out_h_int;
01640 }
01641 }
01642
01643 LoadClient* ScaleEngine::new_client()
01644 {
01645 return new ScaleUnit(this, overlay);
01646 }
01647
01648 LoadPackage* ScaleEngine::new_package()
01649 {
01650 return new ScalePackage;
01651 }
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665 TranslatePackage::TranslatePackage()
01666 {
01667 }
01668
01669
01670
01671 TranslateUnit::TranslateUnit(TranslateEngine *server, OverlayFrame *overlay)
01672 : LoadClient(server)
01673 {
01674 this->overlay = overlay;
01675 this->engine = server;
01676 }
01677
01678 TranslateUnit::~TranslateUnit()
01679 {
01680 }
01681
01682
01683
01684 void TranslateUnit::translation_array_f(transfer_table_f* &table,
01685 float out_x1,
01686 float out_x2,
01687 float in_x1,
01688 float in_x2,
01689 int in_total,
01690 int out_total,
01691 int &out_x1_int,
01692 int &out_x2_int)
01693 {
01694 int out_w_int;
01695 float offset = out_x1 - in_x1;
01696
01697
01698 out_x1_int = (int)out_x1;
01699 out_x2_int = MIN((int)ceil(out_x2), out_total);
01700 out_w_int = out_x2_int - out_x1_int;
01701
01702 table = new transfer_table_f[out_w_int];
01703 bzero(table, sizeof(transfer_table_f) * out_w_int);
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715 float in_x = in_x1;
01716 for(int out_x = out_x1_int; out_x < out_x2_int; out_x++)
01717 {
01718 transfer_table_f *entry = &table[out_x - out_x1_int];
01719
01720 entry->in_x1 = (int)in_x;
01721 entry->in_x2 = (int)in_x + 1;
01722
01723
01724 entry->output_fraction = 1;
01725
01726 if(out_x1 > out_x)
01727 {
01728 entry->output_fraction -= out_x1 - out_x;
01729 }
01730
01731 if(out_x2 < out_x + 1)
01732 {
01733 entry->output_fraction = (out_x2 - out_x);
01734 }
01735
01736
01737 float out_x_fraction = entry->output_fraction;
01738 float in_x_fraction = floor(in_x + 1) - in_x;
01739
01740 if(out_x_fraction <= in_x_fraction)
01741 {
01742 entry->in_fraction1 = out_x_fraction;
01743 entry->in_fraction2 = 0.0;
01744 in_x += out_x_fraction;
01745 }
01746 else
01747 {
01748 entry->in_fraction1 = in_x_fraction;
01749 in_x += out_x_fraction;
01750 entry->in_fraction2 = in_x - floor(in_x);
01751 }
01752
01753
01754 if(entry->in_x2 >= in_total)
01755 {
01756 entry->in_x2 = in_total - 1;
01757 entry->in_fraction2 = 0.0;
01758 }
01759
01760 if(entry->in_x1 >= in_total)
01761 {
01762 entry->in_x1 = in_total - 1;
01763 entry->in_fraction1 = 0.0;
01764 }
01765
01766
01767
01768
01769
01770
01771
01772 }
01773 }
01774
01775
01776 void TranslateUnit::translation_array_i(transfer_table_i* &table,
01777 float out_x1,
01778 float out_x2,
01779 float in_x1,
01780 float in_x2,
01781 int in_total,
01782 int out_total,
01783 int &out_x1_int,
01784 int &out_x2_int)
01785 {
01786 int out_w_int;
01787 float offset = out_x1 - in_x1;
01788
01789 out_x1_int = (int)out_x1;
01790 out_x2_int = MIN((int)ceil(out_x2), out_total);
01791 out_w_int = out_x2_int - out_x1_int;
01792
01793 table = new transfer_table_i[out_w_int];
01794 bzero(table, sizeof(transfer_table_i) * out_w_int);
01795
01796
01797
01798
01799 float in_x = in_x1;
01800 for(int out_x = out_x1_int; out_x < out_x2_int; out_x++)
01801 {
01802 transfer_table_i *entry = &table[out_x - out_x1_int];
01803
01804 entry->in_x1 = (int)in_x;
01805 entry->in_x2 = (int)in_x + 1;
01806
01807
01808 entry->output_fraction = 0x10000;
01809
01810 if(out_x1 > out_x)
01811 {
01812 entry->output_fraction -= (int)((out_x1 - out_x) * 0x10000);
01813 }
01814
01815 if(out_x2 < out_x + 1)
01816 {
01817 entry->output_fraction = (int)((out_x2 - out_x) * 0x10000);
01818 }
01819
01820
01821 int out_x_fraction = entry->output_fraction;
01822 int in_x_fraction = (int)((floor(in_x + 1) - in_x) * 0x10000);
01823
01824 if(out_x_fraction <= in_x_fraction)
01825 {
01826 entry->in_fraction1 = out_x_fraction;
01827 entry->in_fraction2 = 0;
01828 in_x += (float)out_x_fraction / 0x10000;
01829 }
01830 else
01831 {
01832 entry->in_fraction1 = in_x_fraction;
01833 in_x += (float)out_x_fraction / 0x10000;
01834 entry->in_fraction2 = (int)((in_x - floor(in_x)) * 0x10000);
01835 }
01836
01837
01838 if(entry->in_x2 >= in_total)
01839 {
01840 entry->in_x2 = in_total - 1;
01841 entry->in_fraction2 = 0;
01842 }
01843
01844 if(entry->in_x1 >= in_total)
01845 {
01846 entry->in_x1 = in_total - 1;
01847 entry->in_fraction1 = 0;
01848 }
01849
01850
01851
01852
01853
01854
01855
01856 }
01857 }
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892 #define TRANSLATE(max, temp_type, type, components, chroma_offset) \
01893 { \
01894 \
01895 type **in_rows = (type**)input->get_rows(); \
01896 type **out_rows = (type**)output->get_rows(); \
01897 \
01898 \
01899 temp_type master_opacity; \
01900 if(sizeof(type) != 4) \
01901 master_opacity = (temp_type)(alpha * max + 0.5); \
01902 else \
01903 master_opacity = (temp_type)(alpha * max); \
01904 temp_type master_transparency = max - master_opacity; \
01905 float round = 0.0; \
01906 if(sizeof(type) != 4) \
01907 round = 0.5; \
01908 \
01909 \
01910 for(int i = row1; i < row2; i++) \
01911 { \
01912 int in_y1; \
01913 int in_y2; \
01914 float y_fraction1_f; \
01915 float y_fraction2_f; \
01916 float y_output_fraction_f; \
01917 in_y1 = y_table_f[i - out_y1_int].in_x1; \
01918 in_y2 = y_table_f[i - out_y1_int].in_x2; \
01919 y_fraction1_f = y_table_f[i - out_y1_int].in_fraction1; \
01920 y_fraction2_f = y_table_f[i - out_y1_int].in_fraction2; \
01921 y_output_fraction_f = y_table_f[i - out_y1_int].output_fraction; \
01922 type *in_row1 = in_rows[(in_y1)]; \
01923 type *in_row2 = in_rows[(in_y2)]; \
01924 type *out_row = out_rows[i]; \
01925 \
01926 for(int j = out_x1_int; j < out_x2_int; j++) \
01927 { \
01928 int in_x1; \
01929 int in_x2; \
01930 float x_fraction1_f; \
01931 float x_fraction2_f; \
01932 float x_output_fraction_f; \
01933 in_x1 = x_table_f[j - out_x1_int].in_x1; \
01934 in_x2 = x_table_f[j - out_x1_int].in_x2; \
01935 x_fraction1_f = x_table_f[j - out_x1_int].in_fraction1; \
01936 x_fraction2_f = x_table_f[j - out_x1_int].in_fraction2; \
01937 x_output_fraction_f = x_table_f[j - out_x1_int].output_fraction; \
01938 type *output = &out_row[j * components]; \
01939 temp_type input1, input2, input3, input4; \
01940 \
01941 float fraction1 = x_fraction1_f * y_fraction1_f; \
01942 float fraction2 = x_fraction2_f * y_fraction1_f; \
01943 float fraction3 = x_fraction1_f * y_fraction2_f; \
01944 float fraction4 = x_fraction2_f * y_fraction2_f; \
01945 \
01946 input1 = (type)(in_row1[in_x1 * components] * fraction1 + \
01947 in_row1[in_x2 * components] * fraction2 + \
01948 in_row2[in_x1 * components] * fraction3 + \
01949 in_row2[in_x2 * components] * fraction4 + round); \
01950 \
01951 \
01952 if(chroma_offset) \
01953 { \
01954 float extra_chroma = (1.0F - \
01955 fraction1 - \
01956 fraction2 - \
01957 fraction3 - \
01958 fraction4) * chroma_offset; \
01959 input2 = (type)(in_row1[in_x1 * components + 1] * fraction1 + \
01960 in_row1[in_x2 * components + 1] * fraction2 + \
01961 in_row2[in_x1 * components + 1] * fraction3 + \
01962 in_row2[in_x2 * components + 1] * fraction4 + \
01963 extra_chroma + round); \
01964 input3 = (type)(in_row1[in_x1 * components + 2] * fraction1 + \
01965 in_row1[in_x2 * components + 2] * fraction2 + \
01966 in_row2[in_x1 * components + 2] * fraction3 + \
01967 in_row2[in_x2 * components + 2] * fraction4 + \
01968 extra_chroma + round); \
01969 } \
01970 else \
01971 { \
01972 input2 = (type)(in_row1[in_x1 * components + 1] * fraction1 + \
01973 in_row1[in_x2 * components + 1] * fraction2 + \
01974 in_row2[in_x1 * components + 1] * fraction3 + \
01975 in_row2[in_x2 * components + 1] * fraction4 + round); \
01976 input3 = (type)(in_row1[in_x1 * components + 2] * fraction1 + \
01977 in_row1[in_x2 * components + 2] * fraction2 + \
01978 in_row2[in_x1 * components + 2] * fraction3 + \
01979 in_row2[in_x2 * components + 2] * fraction4 + round); \
01980 } \
01981 \
01982 if(components == 4) \
01983 input4 = (type)(in_row1[in_x1 * components + 3] * fraction1 + \
01984 in_row1[in_x2 * components + 3] * fraction2 + \
01985 in_row2[in_x1 * components + 3] * fraction3 + \
01986 in_row2[in_x2 * components + 3] * fraction4 + round); \
01987 \
01988 temp_type opacity; \
01989 if(sizeof(type) != 4) \
01990 opacity = (temp_type)(master_opacity * \
01991 y_output_fraction_f * \
01992 x_output_fraction_f + 0.5); \
01993 else \
01994 opacity = (temp_type)(master_opacity * \
01995 y_output_fraction_f * \
01996 x_output_fraction_f); \
01997 temp_type transparency = max - opacity; \
01998 \
01999 \
02000 \
02001 if(components == 3) \
02002 { \
02003 BLEND_3(max, temp_type, type, chroma_offset); \
02004 } \
02005 else \
02006 { \
02007 BLEND_4(max, temp_type, type, chroma_offset); \
02008 } \
02009 } \
02010 } \
02011 }
02012
02013 void TranslateUnit::process_package(LoadPackage *package)
02014 {
02015 TranslatePackage *pkg = (TranslatePackage*)package;
02016 int out_y1_int;
02017 int out_y2_int;
02018 int out_x1_int;
02019 int out_x2_int;
02020
02021
02022
02023 VFrame *input = engine->translate_input;
02024 VFrame *output = engine->translate_output;
02025 float in_x1 = engine->translate_in_x1;
02026 float in_y1 = engine->translate_in_y1;
02027 float in_x2 = engine->translate_in_x2;
02028 float in_y2 = engine->translate_in_y2;
02029 float out_x1 = engine->translate_out_x1;
02030 float out_y1 = engine->translate_out_y1;
02031 float out_x2 = engine->translate_out_x2;
02032 float out_y2 = engine->translate_out_y2;
02033 float alpha = engine->translate_alpha;
02034 int row1 = pkg->out_row1;
02035 int row2 = pkg->out_row2;
02036 int mode = engine->translate_mode;
02037 int in_total_x = input->get_w();
02038 int in_total_y = input->get_h();
02039 int do_yuv =
02040 (engine->translate_input->get_color_model() == BC_YUV888 ||
02041 engine->translate_input->get_color_model() == BC_YUVA8888 ||
02042 engine->translate_input->get_color_model() == BC_YUV161616 ||
02043 engine->translate_input->get_color_model() == BC_YUVA16161616);
02044
02045 transfer_table_f *x_table_f;
02046 transfer_table_f *y_table_f;
02047 transfer_table_i *x_table_i;
02048 transfer_table_i *y_table_i;
02049
02050 translation_array_f(x_table_f,
02051 out_x1,
02052 out_x2,
02053 in_x1,
02054 in_x2,
02055 in_total_x,
02056 output->get_w(),
02057 out_x1_int,
02058 out_x2_int);
02059 translation_array_f(y_table_f,
02060 out_y1,
02061 out_y2,
02062 in_y1,
02063 in_y2,
02064 in_total_y,
02065 output->get_h(),
02066 out_y1_int,
02067 out_y2_int);
02068
02069
02070
02071
02072 switch(engine->translate_input->get_color_model())
02073 {
02074 case BC_RGB888:
02075 TRANSLATE(0xff, uint32_t, unsigned char, 3, 0);
02076 break;
02077
02078 case BC_RGBA8888:
02079 TRANSLATE(0xff, uint32_t, unsigned char, 4, 0);
02080 break;
02081
02082 case BC_RGB_FLOAT:
02083 TRANSLATE(1.0, float, float, 3, 0);
02084 break;
02085
02086 case BC_RGBA_FLOAT:
02087 TRANSLATE(1.0, float, float, 4, 0);
02088 break;
02089
02090 case BC_RGB161616:
02091 TRANSLATE(0xffff, uint64_t, uint16_t, 3, 0);
02092 break;
02093
02094 case BC_RGBA16161616:
02095 TRANSLATE(0xffff, uint64_t, uint16_t, 4, 0);
02096 break;
02097
02098 case BC_YUV888:
02099 TRANSLATE(0xff, int32_t, unsigned char, 3, 0x80);
02100 break;
02101
02102 case BC_YUVA8888:
02103 TRANSLATE(0xff, int32_t, unsigned char, 4, 0x80);
02104 break;
02105
02106 case BC_YUV161616:
02107 TRANSLATE(0xffff, int64_t, uint16_t, 3, 0x8000);
02108 break;
02109
02110 case BC_YUVA16161616:
02111 TRANSLATE(0xffff, int64_t, uint16_t, 4, 0x8000);
02112 break;
02113 }
02114
02115
02116 delete [] x_table_f;
02117 delete [] y_table_f;
02118 }
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129 TranslateEngine::TranslateEngine(OverlayFrame *overlay, int cpus)
02130 : LoadServer(cpus, cpus)
02131 {
02132 this->overlay = overlay;
02133 }
02134
02135 TranslateEngine::~TranslateEngine()
02136 {
02137 }
02138
02139 void TranslateEngine::init_packages()
02140 {
02141 int out_y1_int = (int)translate_out_y1;
02142 int out_y2_int = MIN((int)ceil(translate_out_y2), translate_output->get_h());
02143 int out_h = out_y2_int - out_y1_int;
02144
02145 for(int i = 0; i < get_total_packages(); i++)
02146 {
02147 TranslatePackage *package = (TranslatePackage*)get_package(i);
02148 package->out_row1 = (int)(out_y1_int + out_h /
02149 get_total_packages() *
02150 i);
02151 package->out_row2 = (int)((float)package->out_row1 +
02152 out_h /
02153 get_total_packages());
02154 if(i >= get_total_packages() - 1)
02155 package->out_row2 = out_y2_int;
02156 }
02157 }
02158
02159 LoadClient* TranslateEngine::new_client()
02160 {
02161 return new TranslateUnit(this, overlay);
02162 }
02163
02164 LoadPackage* TranslateEngine::new_package()
02165 {
02166 return new TranslatePackage;
02167 }
02168
02169
02170
02171
02172
02173
02174
02175
02176 #define SCALE_TRANSLATE(max, temp_type, type, components, chroma_offset) \
02177 { \
02178 temp_type opacity; \
02179 if(sizeof(type) != 4) \
02180 opacity = (temp_type)(alpha * max + 0.5); \
02181 else \
02182 opacity = (temp_type)(alpha * max); \
02183 temp_type transparency = max - opacity; \
02184 \
02185 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
02186 { \
02187 int in_y = y_table[i - out_y1]; \
02188 type *in_row = (type*)in_rows[in_y]; \
02189 type *output = (type*)out_rows[i] + out_x1 * components; \
02190 \
02191 \
02192 if(out_w != in_x2 - in_x1) \
02193 { \
02194 for(int j = 0; j < out_w; j++) \
02195 { \
02196 type *in_row_plus_x = in_row + x_table[j] * components; \
02197 temp_type input1, input2, input3, input4; \
02198 \
02199 input1 = in_row_plus_x[0]; \
02200 input2 = in_row_plus_x[1]; \
02201 input3 = in_row_plus_x[2]; \
02202 if(components == 4) \
02203 input4 = in_row_plus_x[3]; \
02204 \
02205 if(components == 3) \
02206 { \
02207 BLEND_3(max, temp_type, type, chroma_offset); \
02208 } \
02209 else \
02210 { \
02211 BLEND_4(max, temp_type, type, chroma_offset); \
02212 } \
02213 output += components; \
02214 } \
02215 } \
02216 else \
02217 \
02218 { \
02219 in_row += in_x1 * components; \
02220 for(int j = 0; j < out_w; j++) \
02221 { \
02222 temp_type input1, input2, input3, input4; \
02223 \
02224 input1 = in_row[0]; \
02225 input2 = in_row[1]; \
02226 input3 = in_row[2]; \
02227 if(components == 4) \
02228 input4 = in_row[3]; \
02229 \
02230 if(components == 3) \
02231 { \
02232 BLEND_3(max, temp_type, type, chroma_offset); \
02233 } \
02234 else \
02235 { \
02236 BLEND_4(max, temp_type, type, chroma_offset); \
02237 } \
02238 in_row += components; \
02239 output += components; \
02240 } \
02241 } \
02242 } \
02243 }
02244
02245
02246
02247 ScaleTranslateUnit::ScaleTranslateUnit(ScaleTranslateEngine *server, OverlayFrame *overlay)
02248 : LoadClient(server)
02249 {
02250 this->overlay = overlay;
02251 this->scale_translate = server;
02252 }
02253
02254 ScaleTranslateUnit::~ScaleTranslateUnit()
02255 {
02256 }
02257
02258 void ScaleTranslateUnit::scale_array_f(int* &table,
02259 int out_x1,
02260 int out_x2,
02261 float in_x1,
02262 float in_x2)
02263 {
02264 float scale = (float)(out_x2 - out_x1) / (in_x2 - in_x1);
02265
02266 table = new int[(int)out_x2 - out_x1];
02267
02268 for(int i = 0; i < out_x2 - out_x1; i++)
02269 table[i] = (int)((float)i / scale + in_x1);
02270 }
02271
02272 void ScaleTranslateUnit::process_package(LoadPackage *package)
02273 {
02274 ScaleTranslatePackage *pkg = (ScaleTranslatePackage*)package;
02275
02276
02277 VFrame *output = scale_translate->output;
02278 VFrame *input = scale_translate->input;
02279 int in_x1 = (int)scale_translate->in_x1;
02280 int in_y1 = (int)scale_translate->in_y1;
02281 int in_x2 = (int)scale_translate->in_x2;
02282 int in_y2 = (int)scale_translate->in_y2;
02283 int out_x1 = scale_translate->out_x1;
02284 int out_y1 = scale_translate->out_y1;
02285 int out_x2 = scale_translate->out_x2;
02286 int out_y2 = scale_translate->out_y2;
02287 float alpha = scale_translate->alpha;
02288 int mode = scale_translate->mode;
02289 int out_w = out_x2 - out_x1;
02290
02291 int *x_table = 0;
02292 int *y_table;
02293 unsigned char **in_rows = input->get_rows();
02294 unsigned char **out_rows = output->get_rows();
02295
02296
02297
02298
02299 if(out_w != in_x2 - in_x1)
02300 {
02301 scale_array_f(x_table,
02302 out_x1,
02303 out_x2,
02304 scale_translate->in_x1,
02305 scale_translate->in_x2);
02306 }
02307 scale_array_f(y_table,
02308 out_y1,
02309 out_y2,
02310 scale_translate->in_y1,
02311 scale_translate->in_y2);
02312
02313
02314 if (mode == TRANSFER_REPLACE && (out_w == in_x2 - in_x1))
02315 {
02316
02317 char bytes_per_pixel = input->calculate_bytes_per_pixel(input->get_color_model());
02318 int line_len = out_w * bytes_per_pixel;
02319 int in_start_byte = in_x1 * bytes_per_pixel;
02320 int out_start_byte = out_x1 * bytes_per_pixel;
02321 for(int i = pkg->out_row1; i < pkg->out_row2; i++)
02322 {
02323 memcpy (out_rows[i] + out_start_byte,
02324 in_rows[y_table[i - out_y1]] + in_start_byte ,
02325 line_len);
02326 }
02327
02328 }
02329 else
02330 switch(input->get_color_model())
02331 {
02332 case BC_RGB888:
02333 SCALE_TRANSLATE(0xff, uint32_t, uint8_t, 3, 0);
02334 break;
02335
02336 case BC_RGB_FLOAT:
02337 SCALE_TRANSLATE(1.0, float, float, 3, 0);
02338 break;
02339
02340 case BC_YUV888:
02341 SCALE_TRANSLATE(0xff, int32_t, uint8_t, 3, 0x80);
02342 break;
02343
02344 case BC_RGBA8888:
02345 SCALE_TRANSLATE(0xff, uint32_t, uint8_t, 4, 0);
02346 break;
02347
02348 case BC_RGBA_FLOAT:
02349 SCALE_TRANSLATE(1.0, float, float, 4, 0);
02350 break;
02351
02352 case BC_YUVA8888:
02353 SCALE_TRANSLATE(0xff, int32_t, uint8_t, 4, 0x80);
02354 break;
02355
02356
02357 case BC_RGB161616:
02358 SCALE_TRANSLATE(0xffff, uint64_t, uint16_t, 3, 0);
02359 break;
02360
02361 case BC_YUV161616:
02362 SCALE_TRANSLATE(0xffff, int64_t, uint16_t, 3, 0x8000);
02363 break;
02364
02365 case BC_RGBA16161616:
02366 SCALE_TRANSLATE(0xffff, uint64_t, uint16_t, 4, 0);
02367 break;
02368
02369 case BC_YUVA16161616:
02370 SCALE_TRANSLATE(0xffff, int64_t, uint16_t, 4, 0x8000);
02371 break;
02372 }
02373
02374
02375 if(x_table)
02376 delete [] x_table;
02377 delete [] y_table;
02378
02379 };
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389 ScaleTranslateEngine::ScaleTranslateEngine(OverlayFrame *overlay, int cpus)
02390 : LoadServer(cpus, cpus)
02391 {
02392 this->overlay = overlay;
02393 }
02394
02395 ScaleTranslateEngine::~ScaleTranslateEngine()
02396 {
02397 }
02398
02399 void ScaleTranslateEngine::init_packages()
02400 {
02401 int out_h = out_y2 - out_y1;
02402
02403 for(int i = 0; i < get_total_packages(); i++)
02404 {
02405 ScaleTranslatePackage *package = (ScaleTranslatePackage*)get_package(i);
02406 package->out_row1 = (int)(out_y1 + out_h /
02407 get_total_packages() *
02408 i);
02409 package->out_row2 = (int)((float)package->out_row1 +
02410 out_h /
02411 get_total_packages());
02412 if(i >= get_total_packages() - 1)
02413 package->out_row2 = out_y2;
02414 }
02415 }
02416
02417 LoadClient* ScaleTranslateEngine::new_client()
02418 {
02419 return new ScaleTranslateUnit(this, overlay);
02420 }
02421
02422 LoadPackage* ScaleTranslateEngine::new_package()
02423 {
02424 return new ScaleTranslatePackage;
02425 }
02426
02427
02428 ScaleTranslatePackage::ScaleTranslatePackage()
02429 {
02430 }
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459 #define BLEND_ONLY(temp_type, type, max, components, chroma_offset) \
02460 { \
02461 temp_type opacity; \
02462 if(sizeof(type) != 4) \
02463 opacity = (temp_type)(alpha * max + 0.5); \
02464 else \
02465 opacity = (temp_type)(alpha * max); \
02466 temp_type transparency = max - opacity; \
02467 \
02468 type** output_rows = (type**)output->get_rows(); \
02469 type** input_rows = (type**)input->get_rows(); \
02470 int w = input->get_w(); \
02471 int h = input->get_h(); \
02472 \
02473 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
02474 { \
02475 type* in_row = input_rows[i]; \
02476 type* output = output_rows[i]; \
02477 \
02478 for(int j = 0; j < w; j++) \
02479 { \
02480 temp_type input1, input2, input3, input4; \
02481 input1 = in_row[0]; \
02482 input2 = in_row[1]; \
02483 input3 = in_row[2]; \
02484 if(components == 4) input4 = in_row[3]; \
02485 \
02486 \
02487 if(components == 3) \
02488 { \
02489 BLEND_3(max, temp_type, type, chroma_offset); \
02490 } \
02491 else \
02492 { \
02493 BLEND_4(max, temp_type, type, chroma_offset); \
02494 } \
02495 \
02496 in_row += components; \
02497 output += components; \
02498 } \
02499 } \
02500 }
02501
02502
02503 #define BLEND_ONLY_TRANSFER_REPLACE(type, components) \
02504 { \
02505 \
02506 type** output_rows = (type**)output->get_rows(); \
02507 type** input_rows = (type**)input->get_rows(); \
02508 int w = input->get_w(); \
02509 int h = input->get_h(); \
02510 int line_len = w * sizeof(type) * components; \
02511 \
02512 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
02513 { \
02514 memcpy(output_rows[i], input_rows[i], line_len); \
02515 } \
02516 }
02517
02518
02519 #define BLEND_ONLY_4_NORMAL(temp_type, type, max, chroma_offset) \
02520 { \
02521 temp_type opacity = (temp_type)(alpha * max + 0.5); \
02522 temp_type transparency = max - opacity; \
02523 temp_type max_squared = ((temp_type)max) * max; \
02524 \
02525 type** output_rows = (type**)output->get_rows(); \
02526 type** input_rows = (type**)input->get_rows(); \
02527 int w = input->get_w(); \
02528 int h = input->get_h(); \
02529 \
02530 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
02531 { \
02532 type* in_row = input_rows[i]; \
02533 type* output = output_rows[i]; \
02534 \
02535 for(int j = 0; j < w; j++) \
02536 { \
02537 temp_type pixel_opacity, pixel_transparency; \
02538 pixel_opacity = opacity * in_row[3]; \
02539 pixel_transparency = (temp_type)max_squared - pixel_opacity; \
02540 \
02541 \
02542 temp_type r,g,b; \
02543 output[0] = ((temp_type)in_row[0] * pixel_opacity + \
02544 (temp_type)output[0] * pixel_transparency) / max / max; \
02545 output[1] = (((temp_type)in_row[1] - chroma_offset) * pixel_opacity + \
02546 ((temp_type)output[1] - chroma_offset) * pixel_transparency) \
02547 / max / max + \
02548 chroma_offset; \
02549 output[2] = (((temp_type)in_row[2] - chroma_offset) * pixel_opacity + \
02550 ((temp_type)output[2] - chroma_offset) * pixel_transparency) \
02551 / max / max + \
02552 chroma_offset; \
02553 output[3] = (type)(in_row[3] > output[3] ? in_row[3] : output[3]); \
02554 \
02555 in_row += 4; \
02556 output += 4; \
02557 } \
02558 } \
02559 }
02560
02561
02562
02563
02564 #define BLEND_ONLY_3_NORMAL(temp_type, type, max, chroma_offset) \
02565 { \
02566 const int bits = sizeof(type) * 8; \
02567 temp_type opacity = (temp_type)(alpha * ((temp_type)1 << bits) + 0.5); \
02568 temp_type transparency = ((temp_type)1 << bits) - opacity; \
02569 \
02570 type** output_rows = (type**)output->get_rows(); \
02571 type** input_rows = (type**)input->get_rows(); \
02572 int w = input->get_w() * 3; \
02573 int h = input->get_h(); \
02574 \
02575 for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
02576 { \
02577 type* in_row = input_rows[i]; \
02578 type* output = output_rows[i]; \
02579 \
02580 for(int j = 0; j < w; j++) \
02581 { \
02582 *output = ((temp_type)*in_row * opacity + *output * transparency) >> bits; \
02583 in_row ++; \
02584 output ++; \
02585 } \
02586 } \
02587 }
02588
02589
02590
02591 BlendUnit::BlendUnit(BlendEngine *server, OverlayFrame *overlay)
02592 : LoadClient(server)
02593 {
02594 this->overlay = overlay;
02595 this->blend_engine = server;
02596 }
02597
02598 BlendUnit::~BlendUnit()
02599 {
02600 }
02601
02602 void BlendUnit::process_package(LoadPackage *package)
02603 {
02604 BlendPackage *pkg = (BlendPackage*)package;
02605
02606
02607 VFrame *output = blend_engine->output;
02608 VFrame *input = blend_engine->input;
02609 float alpha = blend_engine->alpha;
02610 int mode = blend_engine->mode;
02611
02612 if (mode == TRANSFER_REPLACE)
02613 {
02614 switch(input->get_color_model())
02615 {
02616 case BC_RGB_FLOAT:
02617 BLEND_ONLY_TRANSFER_REPLACE(float, 3);
02618 break;
02619 case BC_RGBA_FLOAT:
02620 BLEND_ONLY_TRANSFER_REPLACE(float, 4);
02621 break;
02622 case BC_RGB888:
02623 case BC_YUV888:
02624 BLEND_ONLY_TRANSFER_REPLACE(unsigned char, 3);
02625 break;
02626 case BC_RGBA8888:
02627 case BC_YUVA8888:
02628 BLEND_ONLY_TRANSFER_REPLACE(unsigned char, 4);
02629 break;
02630 case BC_RGB161616:
02631 case BC_YUV161616:
02632 BLEND_ONLY_TRANSFER_REPLACE(uint16_t, 3);
02633 break;
02634 case BC_RGBA16161616:
02635 case BC_YUVA16161616:
02636 BLEND_ONLY_TRANSFER_REPLACE(uint16_t, 4);
02637 break;
02638 }
02639 }
02640 else
02641 if (mode == TRANSFER_NORMAL)
02642 {
02643 switch(input->get_color_model())
02644 {
02645 case BC_RGB_FLOAT:
02646 {
02647 float opacity = alpha;
02648 float transparency = 1.0 - alpha;
02649
02650 float** output_rows = (float**)output->get_rows();
02651 float** input_rows = (float**)input->get_rows();
02652 int w = input->get_w() * 3;
02653 int h = input->get_h();
02654
02655 for(int i = pkg->out_row1; i < pkg->out_row2; i++)
02656 {
02657 float* in_row = input_rows[i];
02658 float* output = output_rows[i];
02659
02660 for(int j = 0; j < w; j++)
02661 {
02662 *output = *in_row * opacity + *output * transparency;
02663 in_row++;
02664 output++;
02665 }
02666 }
02667 break;
02668 }
02669 case BC_RGBA_FLOAT:
02670 {
02671 float opacity = alpha;
02672 float transparency = 1.0 - alpha;
02673
02674 float** output_rows = (float**)output->get_rows();
02675 float** input_rows = (float**)input->get_rows();
02676 int w = input->get_w();
02677 int h = input->get_h();
02678
02679 for(int i = pkg->out_row1; i < pkg->out_row2; i++)
02680 {
02681 float* in_row = input_rows[i];
02682 float* output = output_rows[i];
02683
02684 for(int j = 0; j < w; j++)
02685 {
02686 float pixel_opacity, pixel_transparency;
02687 pixel_opacity = opacity * in_row[3];
02688 pixel_transparency = 1.0 - pixel_opacity;
02689
02690
02691 output[0] = in_row[0] * pixel_opacity +
02692 output[0] * pixel_transparency;
02693 output[1] = in_row[1] * pixel_opacity +
02694 output[1] * pixel_transparency;
02695 output[2] = in_row[2] * pixel_opacity +
02696 output[2] * pixel_transparency;
02697 output[3] = in_row[3] > output[3] ? in_row[3] : output[3];
02698
02699 in_row += 4;
02700 output += 4;
02701 }
02702 }
02703 break;
02704 }
02705 case BC_RGB888:
02706 BLEND_ONLY_3_NORMAL(uint32_t, unsigned char, 0xff, 0);
02707 break;
02708 case BC_YUV888:
02709 BLEND_ONLY_3_NORMAL(int32_t, unsigned char, 0xff, 0x80);
02710 break;
02711 case BC_RGBA8888:
02712 BLEND_ONLY_4_NORMAL(uint32_t, unsigned char, 0xff, 0);
02713 break;
02714 case BC_YUVA8888:
02715 BLEND_ONLY_4_NORMAL(int32_t, unsigned char, 0xff, 0x80);
02716 break;
02717 case BC_RGB161616:
02718 BLEND_ONLY_3_NORMAL(uint64_t, uint16_t, 0xffff, 0);
02719 break;
02720 case BC_YUV161616:
02721 BLEND_ONLY_3_NORMAL(int64_t, uint16_t, 0xffff, 0x8000);
02722 break;
02723 case BC_RGBA16161616:
02724 BLEND_ONLY_4_NORMAL(uint64_t, uint16_t, 0xffff, 0);
02725 break;
02726 case BC_YUVA16161616:
02727 BLEND_ONLY_4_NORMAL(int64_t, uint16_t, 0xffff, 0x8000);
02728 break;
02729 }
02730 }
02731 else
02732 switch(input->get_color_model())
02733 {
02734 case BC_RGB_FLOAT:
02735 BLEND_ONLY(float, float, 1.0, 3, 0);
02736 break;
02737 case BC_RGBA_FLOAT:
02738 BLEND_ONLY(float, float, 1.0, 4, 0);
02739 break;
02740 case BC_RGB888:
02741 BLEND_ONLY(int32_t, unsigned char, 0xff, 3, 0);
02742 break;
02743 case BC_YUV888:
02744 BLEND_ONLY(int32_t, unsigned char, 0xff, 3, 0x80);
02745 break;
02746 case BC_RGBA8888:
02747 BLEND_ONLY(int32_t, unsigned char, 0xff, 4, 0);
02748 break;
02749 case BC_YUVA8888:
02750 BLEND_ONLY(int32_t, unsigned char, 0xff, 4, 0x80);
02751 break;
02752 case BC_RGB161616:
02753 BLEND_ONLY(int64_t, uint16_t, 0xffff, 3, 0);
02754 break;
02755 case BC_YUV161616:
02756 BLEND_ONLY(int64_t, uint16_t, 0xffff, 3, 0x8000);
02757 break;
02758 case BC_RGBA16161616:
02759 BLEND_ONLY(int64_t, uint16_t, 0xffff, 4, 0);
02760 break;
02761 case BC_YUVA16161616:
02762 BLEND_ONLY(int64_t, uint16_t, 0xffff, 4, 0x8000);
02763 break;
02764 }
02765 }
02766
02767
02768
02769 BlendEngine::BlendEngine(OverlayFrame *overlay, int cpus)
02770 : LoadServer(cpus, cpus)
02771 {
02772 this->overlay = overlay;
02773 }
02774
02775 BlendEngine::~BlendEngine()
02776 {
02777 }
02778
02779 void BlendEngine::init_packages()
02780 {
02781 for(int i = 0; i < get_total_packages(); i++)
02782 {
02783 BlendPackage *package = (BlendPackage*)get_package(i);
02784 package->out_row1 = (int)(input->get_h() /
02785 get_total_packages() *
02786 i);
02787 package->out_row2 = (int)((float)package->out_row1 +
02788 input->get_h() /
02789 get_total_packages());
02790
02791 if(i >= get_total_packages() - 1)
02792 package->out_row2 = input->get_h();
02793 }
02794 }
02795
02796 LoadClient* BlendEngine::new_client()
02797 {
02798 return new BlendUnit(this, overlay);
02799 }
02800
02801 LoadPackage* BlendEngine::new_package()
02802 {
02803 return new BlendPackage;
02804 }
02805
02806
02807 BlendPackage::BlendPackage()
02808 {
02809 }
02810
02811