rework keyframe hide popup, keyframe auto render, textbox set_selection wide text
[goodguy/history.git] / cinelerra-5.1 / cinelerra / overlayframe.C.float
1 #include <math.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdint.h>
5
6 #include "clip.h"
7 #include "edl.inc"
8 #include "overlayframe.h"
9 #include "vframe.h"
10
11 OverlayFrame::OverlayFrame(int cpus)
12 {
13         temp_frame = 0;
14         blend_engine = 0;
15         scale_engine = 0;
16         scaletranslate_engine = 0;
17         translate_engine = 0;
18         this->cpus = cpus;
19 }
20
21 OverlayFrame::~OverlayFrame()
22 {
23 //printf("OverlayFrame::~OverlayFrame 1\n");
24         if(temp_frame) delete temp_frame;
25         if(scale_engine) delete scale_engine;
26         if(translate_engine) delete translate_engine;
27         if(blend_engine) delete blend_engine;
28         if(scaletranslate_engine) delete scaletranslate_engine;
29 //printf("OverlayFrame::~OverlayFrame 2\n");
30 }
31
32
33
34
35
36
37
38
39 // Verification: 
40
41 // (255 * 255 + 0 * 0) / 255 = 255
42 // (255 * 127 + 255 * (255 - 127)) / 255 = 255
43
44 // (65535 * 65535 + 0 * 0) / 65535 = 65535
45 // (65535 * 32767 + 65535 * (65535 - 32767)) / 65535 = 65535
46
47
48 // Branch prediction 4 U
49
50 #define BLEND_3(max, type) \
51 { \
52         int64_t r, g, b; \
53  \
54 /* if(mode != TRANSFER_NORMAL) printf("BLEND mode = %d\n", mode); */ \
55         switch(mode) \
56         { \
57                 case TRANSFER_DIVIDE: \
58                         r = output[0] ? (((int64_t)input1 * max) / output[0]) : max; \
59                         g = output[1] ? (((int64_t)input2 * max) / output[1]) : max; \
60                         b = output[2] ? (((int64_t)input3 * max) / output[2]) : max; \
61                         r = (r * opacity + output[0] * transparency) / max; \
62                         g = (g * opacity + output[1] * transparency) / max; \
63                         b = (b * opacity + output[2] * transparency) / max; \
64                         break; \
65                 case TRANSFER_MULTIPLY: \
66                         r = ((int64_t)input1 * output[0]) / max; \
67                         g = ((int64_t)input2 * output[1]) / max; \
68                         b = ((int64_t)input3 * output[2]) / max; \
69                         r = (r * opacity + output[0] * transparency) / max; \
70                         g = (g * opacity + output[1] * transparency) / max; \
71                         b = (b * opacity + output[2] * transparency) / max; \
72                         break; \
73                 case TRANSFER_SUBTRACT: \
74                         r = (((int64_t)input1 - output[0]) * opacity + output[0] * transparency) / max; \
75                         g = (((int64_t)input2 - output[1]) * opacity + output[1] * transparency) / max; \
76                         b = (((int64_t)input3 - output[2]) * opacity + output[2] * transparency) / max; \
77                         break; \
78                 case TRANSFER_ADDITION: \
79                         r = (((int64_t)input1 + output[0]) * opacity + output[0] * transparency) / max; \
80                         g = (((int64_t)input2 + output[1]) * opacity + output[1] * transparency) / max; \
81                         b = (((int64_t)input3 + output[2]) * opacity + output[2] * transparency) / max; \
82                         break; \
83                 case TRANSFER_REPLACE: \
84                         r = input1; \
85                         g = input2; \
86                         b = input3; \
87                         break; \
88                 case TRANSFER_NORMAL: \
89                         r = ((int64_t)input1 * opacity + output[0] * transparency) / max; \
90                         g = ((int64_t)input2 * opacity + output[1] * transparency) / max; \
91                         b = ((int64_t)input3 * opacity + output[2] * transparency) / max; \
92                         break; \
93         } \
94  \
95         output[0] = (type)CLIP(r, 0, max); \
96         output[1] = (type)CLIP(g, 0, max); \
97         output[2] = (type)CLIP(b, 0, max); \
98 }
99
100
101
102
103
104 // Blending equations are drastically different for 3 and 4 components
105 #define BLEND_4(max, type) \
106 { \
107         int64_t r, g, b, a; \
108         int64_t pixel_opacity, pixel_transparency; \
109  \
110         pixel_opacity = opacity * input4 / max; \
111         pixel_transparency = (max - pixel_opacity) * output[3] / max; \
112  \
113         switch(mode) \
114         { \
115                 case TRANSFER_DIVIDE: \
116                         r = output[0] ? (((int64_t)input1 * max) / output[0]) : max; \
117                         g = output[1] ? (((int64_t)input2 * max) / output[1]) : max; \
118                         b = output[2] ? (((int64_t)input3 * max) / output[2]) : max; \
119                         r = (r * pixel_opacity + output[0] * pixel_transparency) / max; \
120                         g = (g * pixel_opacity + output[1] * pixel_transparency) / max; \
121                         b = (b * pixel_opacity + output[2] * pixel_transparency) / max; \
122                         a = input4 > output[3] ? input4 : output[3]; \
123                         break; \
124                 case TRANSFER_MULTIPLY: \
125                         r = ((int64_t)input1 * output[0]) / max; \
126                         g = ((int64_t)input2 * output[1]) / max; \
127                         b = ((int64_t)input3 * output[2]) / max; \
128                         r = (r * pixel_opacity + output[0] * pixel_transparency) / max; \
129                         g = (g * pixel_opacity + output[1] * pixel_transparency) / max; \
130                         b = (b * pixel_opacity + output[2] * pixel_transparency) / max; \
131                         a = input4 > output[3] ? input4 : output[3]; \
132                         break; \
133                 case TRANSFER_SUBTRACT: \
134                         r = (((int64_t)input1 - output[0]) * pixel_opacity + output[0] * pixel_transparency) / max; \
135                         g = (((int64_t)input2 - output[1]) * pixel_opacity + output[1] * pixel_transparency) / max; \
136                         b = (((int64_t)input3 - output[2]) * pixel_opacity + output[2] * pixel_transparency) / max; \
137                         a = input4 > output[3] ? input4 : output[3]; \
138                         break; \
139                 case TRANSFER_ADDITION: \
140                         r = (((int64_t)input1 + output[0]) * pixel_opacity + output[0] * pixel_transparency) / max; \
141                         g = (((int64_t)input2 + output[1]) * pixel_opacity + output[1] * pixel_transparency) / max; \
142                         b = (((int64_t)input3 + output[2]) * pixel_opacity + output[2] * pixel_transparency) / max; \
143                         a = input4 > output[3] ? input4 : output[3]; \
144                         break; \
145                 case TRANSFER_REPLACE: \
146                         r = input1; \
147                         g = input2; \
148                         b = input3; \
149                         a = input4; \
150                         break; \
151                 case TRANSFER_NORMAL: \
152                         r = ((int64_t)input1 * pixel_opacity + output[0] * pixel_transparency) / max; \
153                         g = ((int64_t)input2 * pixel_opacity + output[1] * pixel_transparency) / max; \
154                         b = ((int64_t)input3 * pixel_opacity + output[2] * pixel_transparency) / max; \
155                         a = input4 > output[3] ? input4 : output[3]; \
156                         break; \
157         } \
158  \
159         output[0] = (type)CLIP(r, 0, max); \
160         output[1] = (type)CLIP(g, 0, max); \
161         output[2] = (type)CLIP(b, 0, max); \
162         output[3] = (type)a; \
163 }
164
165
166
167
168
169
170
171
172 // Bicubic algorithm using multiprocessors
173 // input -> scale nearest integer boundaries -> temp -> translation -> blend -> output
174
175 // Nearest neighbor algorithm using multiprocessors for blending
176 // input -> scale + translate -> blend -> output
177
178
179 int OverlayFrame::overlay(VFrame *output, 
180         VFrame *input, 
181         float in_x1, 
182         float in_y1, 
183         float in_x2, 
184         float in_y2, 
185         float out_x1, 
186         float out_y1, 
187         float out_x2, 
188         float out_y2, 
189         float alpha,       // 0 - 1
190         int mode,
191         int interpolation_type)
192 {
193         float w_scale = (out_x2 - out_x1) / (in_x2 - in_x1);
194         float h_scale = (out_y2 - out_y1) / (in_y2 - in_y1);
195
196 //printf("OverlayFrame::overlay 1 %d %f\n", mode, alpha);
197 // Limit values
198         if(in_x1 < 0)
199         {
200                 out_x1 += -in_x1 * w_scale;
201                 in_x1 = 0;
202         }
203         else
204         if(in_x1 >= input->get_w())
205         {
206                 out_x1 -= (in_x1 - input->get_w()) * w_scale;
207                 in_x1 = input->get_w();
208         }
209
210         if(in_y1 < 0)
211         {
212                 out_y1 += -in_y1 * h_scale;
213                 in_y1 = 0;
214         }
215         else
216         if(in_y1 >= input->get_h())
217         {
218                 out_y1 -= (in_y1 - input->get_h()) * h_scale;
219                 in_y1 = input->get_h();
220         }
221
222         if(in_x2 < 0)
223         {
224                 out_x2 += -in_x2 * w_scale;
225                 in_x2 = 0;
226         }
227         else
228         if(in_x2 >= input->get_w())
229         {
230                 out_x2 -= (in_x2 - input->get_w()) * w_scale;
231                 in_x2 = input->get_w();
232         }
233
234         if(in_y2 < 0)
235         {
236                 out_y2 += -in_y2 * h_scale;
237                 in_y2 = 0;
238         }
239         else
240         if(in_y2 >= input->get_h())
241         {
242                 out_y2 -= (in_y2 - input->get_h()) * h_scale;
243                 in_y2 = input->get_h();
244         }
245
246         if(out_x1 < 0)
247         {
248                 in_x1 += -out_x1 / w_scale;
249                 out_x1 = 0;
250         }
251         else
252         if(out_x1 >= output->get_w())
253         {
254                 in_x1 -= (out_x1 - output->get_w()) / w_scale;
255                 out_x1 = output->get_w();
256         }
257
258         if(out_y1 < 0)
259         {
260                 in_y1 += -out_y1 / h_scale;
261                 out_y1 = 0;
262         }
263         else
264         if(out_y1 >= output->get_h())
265         {
266                 in_y1 -= (out_y1 - output->get_h()) / h_scale;
267                 out_y1 = output->get_h();
268         }
269
270         if(out_x2 < 0)
271         {
272                 in_x2 += -out_x2 / w_scale;
273                 out_x2 = 0;
274         }
275         else
276         if(out_x2 >= output->get_w())
277         {
278                 in_x2 -= (out_x2 - output->get_w()) / w_scale;
279                 out_x2 = output->get_w();
280         }
281
282         if(out_y2 < 0)
283         {
284                 in_y2 += -out_y2 / h_scale;
285                 out_y2 = 0;
286         }
287         else
288         if(out_y2 >= output->get_h())
289         {
290                 in_y2 -= (out_y2 - output->get_h()) / h_scale;
291                 out_y2 = output->get_h();
292         }
293
294
295
296
297
298         float in_w = in_x2 - in_x1;
299         float in_h = in_y2 - in_y1;
300         float out_w = out_x2 - out_x1;
301         float out_h = out_y2 - out_y1;
302 // Input for translation operation
303         VFrame *translation_input = input;
304
305
306
307 // printf("OverlayFrame::overlay %f %f %f %f -> %f %f %f %f\n", in_x1,
308 //                      in_y1,
309 //                      in_x2,
310 //                      in_y2,
311 //                      out_x1,
312 //                      out_y1,
313 //                      out_x2,
314 //                      out_y2);
315
316
317
318
319
320 // ****************************************************************************
321 // Transfer to temp buffer by scaling nearest integer boundaries
322 // ****************************************************************************
323         if(interpolation_type != NEAREST_NEIGHBOR &&
324                 (!EQUIV(w_scale, 1) || !EQUIV(h_scale, 1)))
325         {
326 // Create integer boundaries for interpolation
327                 int in_x1_int = (int)in_x1;
328                 int in_y1_int = (int)in_y1;
329                 int in_x2_int = MIN((int)ceil(in_x2), input->get_w());
330                 int in_y2_int = MIN((int)ceil(in_y2), input->get_h());
331
332 // Dimensions of temp frame.  Integer boundaries scaled.
333                 int temp_w = (int)ceil(w_scale * (in_x2_int - in_x1_int));
334                 int temp_h = (int)ceil(h_scale * (in_y2_int - in_y1_int));
335                 VFrame *scale_output;
336
337
338
339 #define NO_TRANSLATION1 \
340         (EQUIV(in_x1, 0) && \
341         EQUIV(in_y1, 0) && \
342         EQUIV(out_x1, 0) && \
343         EQUIV(out_y1, 0) && \
344         EQUIV(in_x2, in_x2_int) && \
345         EQUIV(in_y2, in_y2_int) && \
346         EQUIV(out_x2, temp_w) && \
347         EQUIV(out_y2, temp_h))
348
349
350 #define NO_BLEND \
351         (EQUIV(alpha, 1) && \
352         (mode == TRANSFER_REPLACE || \
353         (mode == TRANSFER_NORMAL && cmodel_components(input->get_color_model()) == 3)))
354
355
356
357
358
359 // Prepare destination for operation
360
361 // No translation and no blending.  The blending operation is built into the
362 // translation unit but not the scaling unit.
363 // input -> output
364                 if(NO_TRANSLATION1 &&
365                         NO_BLEND)
366                 {
367 // printf("OverlayFrame::overlay input -> output\n");
368
369                         scale_output = output;
370                         translation_input = 0;
371                 }
372                 else
373 // If translation or blending
374 // input -> nearest integer boundary temp
375                 {
376                         if(temp_frame && 
377                                 (temp_frame->get_w() != temp_w ||
378                                         temp_frame->get_h() != temp_h))
379                         {
380                                 delete temp_frame;
381                                 temp_frame = 0;
382                         }
383
384                         if(!temp_frame)
385                         {
386                                 temp_frame = new VFrame(0,
387                                         temp_w,
388                                         temp_h,
389                                         input->get_color_model(),
390                                         -1);
391                         }
392 //printf("OverlayFrame::overlay input -> temp\n");
393
394
395                         temp_frame->clear_frame();
396
397 // printf("OverlayFrame::overlay 4 temp_w=%d temp_h=%d\n",
398 //      temp_w, temp_h);
399                         scale_output = temp_frame;
400                         translation_input = scale_output;
401
402 // Adjust input coordinates to reflect new scaled coordinates.
403                         in_x1 = (in_x1 - in_x1_int) * w_scale;
404                         in_y1 = (in_y1 - in_y1_int) * h_scale;
405                         in_x2 = (in_x2 - in_x1_int) * w_scale;
406                         in_y2 = (in_y2 - in_y1_int) * h_scale;
407                 }
408
409
410
411
412 // Scale input -> scale_output
413                 this->scale_output = scale_output;
414                 this->scale_input = input;
415                 this->w_scale = w_scale;
416                 this->h_scale = h_scale;
417                 this->in_x1_int = in_x1_int;
418                 this->in_y1_int = in_y1_int;
419                 this->out_w_int = temp_w;
420                 this->out_h_int = temp_h;
421                 this->interpolation_type = interpolation_type;
422
423 //printf("OverlayFrame::overlay ScaleEngine 1 %d\n", out_h_int);
424                 if(!scale_engine) scale_engine = new ScaleEngine(this, cpus);
425                 scale_engine->process_packages();
426 //printf("OverlayFrame::overlay ScaleEngine 2\n");
427
428
429
430         }
431
432 // printf("OverlayFrame::overlay 1  %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", 
433 //      in_x1, 
434 //      in_y1, 
435 //      in_x2, 
436 //      in_y2, 
437 //      out_x1, 
438 //      out_y1, 
439 //      out_x2, 
440 //      out_y2);
441
442
443
444
445
446 #define NO_TRANSLATION2 \
447         (EQUIV(in_x1, 0) && \
448         EQUIV(in_y1, 0) && \
449         EQUIV(in_x2, translation_input->get_w()) && \
450         EQUIV(in_y2, translation_input->get_h()) && \
451         EQUIV(out_x1, 0) && \
452         EQUIV(out_y1, 0) && \
453         EQUIV(out_x2, output->get_w()) && \
454         EQUIV(out_y2, output->get_h())) \
455
456 #define NO_SCALE \
457         (EQUIV(out_x2 - out_x1, in_x2 - in_x1) && \
458         EQUIV(out_y2 - out_y1, in_y2 - in_y1))
459
460         
461
462
463 //printf("OverlayFrame::overlay 4 %d\n", mode);
464
465
466
467
468         if(translation_input)
469         {
470 // Direct copy
471                 if( NO_TRANSLATION2 &&
472                         NO_SCALE &&
473                         NO_BLEND)
474                 {
475 //printf("OverlayFrame::overlay direct copy\n");
476                         output->copy_from(translation_input);
477                 }
478                 else
479 // Blend only
480                 if( NO_TRANSLATION2 &&
481                         NO_SCALE)
482                 {
483                         if(!blend_engine) blend_engine = new BlendEngine(this, cpus);
484
485
486                         blend_engine->output = output;
487                         blend_engine->input = translation_input;
488                         blend_engine->alpha = alpha;
489                         blend_engine->mode = mode;
490
491                         blend_engine->process_packages();
492                 }
493                 else
494 // Scale and translate using nearest neighbor
495 // Translation is exactly on integer boundaries
496                 if(interpolation_type == NEAREST_NEIGHBOR ||
497                         EQUIV(in_x1, (int)in_x1) &&
498                         EQUIV(in_y1, (int)in_y1) &&
499                         EQUIV(in_x2, (int)in_x2) &&
500                         EQUIV(in_y2, (int)in_y2) &&
501
502                         EQUIV(out_x1, (int)out_x1) &&
503                         EQUIV(out_y1, (int)out_y1) &&
504                         EQUIV(out_x2, (int)out_x2) &&
505                         EQUIV(out_y2, (int)out_y2))
506                 {
507 //printf("OverlayFrame::overlay NEAREST_NEIGHBOR 1\n");
508                         if(!scaletranslate_engine) scaletranslate_engine = new ScaleTranslateEngine(this, cpus);
509
510
511                         scaletranslate_engine->output = output;
512                         scaletranslate_engine->input = translation_input;
513                         scaletranslate_engine->in_x1 = (int)in_x1;
514                         scaletranslate_engine->in_y1 = (int)in_y1;
515                         scaletranslate_engine->in_x2 = (int)in_x2;
516                         scaletranslate_engine->in_y2 = (int)in_y2;
517                         scaletranslate_engine->out_x1 = (int)out_x1;
518                         scaletranslate_engine->out_y1 = (int)out_y1;
519                         scaletranslate_engine->out_x2 = (int)out_x2;
520                         scaletranslate_engine->out_y2 = (int)out_y2;
521                         scaletranslate_engine->alpha = alpha;
522                         scaletranslate_engine->mode = mode;
523
524                         scaletranslate_engine->process_packages();
525                 }
526                 else
527 // Fractional translation
528                 {
529 // Use fractional translation
530 // printf("OverlayFrame::overlay temp -> output  %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n", 
531 //      in_x1, 
532 //      in_y1, 
533 //      in_x2, 
534 //      in_y2, 
535 //      out_x1, 
536 //      out_y1, 
537 //      out_x2, 
538 //      out_y2);
539                         this->translate_output = output;
540                         this->translate_input = translation_input;
541                         this->translate_in_x1 = in_x1;
542                         this->translate_in_y1 = in_y1;
543                         this->translate_in_x2 = in_x2;
544                         this->translate_in_y2 = in_y2;
545                         this->translate_out_x1 = out_x1;
546                         this->translate_out_y1 = out_y1;
547                         this->translate_out_x2 = out_x2;
548                         this->translate_out_y2 = out_y2;
549                         this->translate_alpha = alpha;
550                         this->translate_mode = mode;
551
552 //printf("OverlayFrame::overlay 5 %d\n", mode);
553                         if(!translate_engine) translate_engine = new TranslateEngine(this, cpus);
554                         translate_engine->process_packages();
555
556                 }
557         }
558 //printf("OverlayFrame::overlay 2\n");
559
560         return 0;
561 }
562
563
564
565
566
567
568
569 ScalePackage::ScalePackage()
570 {
571 }
572
573
574
575
576 ScaleUnit::ScaleUnit(ScaleEngine *server, OverlayFrame *overlay)
577  : LoadClient(server)
578 {
579         this->overlay = overlay;
580 }
581
582 ScaleUnit::~ScaleUnit()
583 {
584 }
585
586
587
588 #define BILINEAR(max, type, components) \
589 { \
590         float k_y = 1.0 / scale_h; \
591         float k_x = 1.0 / scale_w; \
592         type **in_rows = (type**)input->get_rows(); \
593         type **out_rows = (type**)output->get_rows(); \
594         type zero_r, zero_g, zero_b, zero_a; \
595         int in_h_int = input->get_h(); \
596         int in_w_int = input->get_w(); \
597  \
598         zero_r = 0; \
599         zero_g = ((max + 1) >> 1) * (do_yuv); \
600         zero_b = ((max + 1) >> 1) * (do_yuv); \
601         if(components == 4) zero_a = 0; \
602  \
603  \
604         for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
605         { \
606                 float f_y = (float)i * k_y; \
607                 int i_y = (int)floor(f_y); \
608                 float a = f_y - floor(f_y); \
609                 type *in_row1 = in_rows[i_y + in_y1_int]; \
610                 type *in_row2 = (i_y + in_y1_int < in_h_int - 1) ?  \
611                         in_rows[i_y + in_y1_int + 1] : \
612                         0; \
613                 type *out_row = out_rows[i]; \
614  \
615                 for(int j = 0; j < out_w_int; j++) \
616                 { \
617                         float f_x = (float)j * k_x; \
618                         int i_x = (int)floor(f_x); \
619                         float b = f_x - floor(f_x); \
620                         int x = i_x + in_x1_int; \
621                         float output1r, output1g, output1b, output1a; \
622                         float output2r, output2g, output2b, output2a; \
623                         float output3r, output3g, output3b, output3a; \
624                         float output4r, output4g, output4b, output4a; \
625  \
626                         output1r = in_row1[x * components]; \
627                         output1g = in_row1[x * components + 1]; \
628                         output1b = in_row1[x * components + 2]; \
629                         if(components == 4) output1a = in_row1[x * components + 3]; \
630  \
631                         if(x < in_w_int - 1) \
632                         { \
633                                 output2r = in_row1[x * components + components]; \
634                                 output2g = in_row1[x * components + components + 1]; \
635                                 output2b = in_row1[x * components + components + 2]; \
636                                 if(components == 4) output2a = in_row1[x * components + components + 3]; \
637  \
638                                 if(in_row2) \
639                                 { \
640                                         output4r = in_row2[x * components + components]; \
641                                         output4g = in_row2[x * components + components + 1]; \
642                                         output4b = in_row2[x * components + components + 2]; \
643                                         if(components == 4) output4a = in_row2[x * components + components + 3]; \
644                                 } \
645                                 else \
646                                 { \
647                                         output4r = zero_r; \
648                                         output4g = zero_g; \
649                                         output4b = zero_b; \
650                                         if(components == 4) output4a = zero_a; \
651                                 } \
652                         } \
653                         else \
654                         { \
655                                 output2r = zero_r; \
656                                 output2g = zero_g; \
657                                 output2b = zero_b; \
658                                 if(components == 4) output2a = zero_a; \
659                                 output4r = zero_r; \
660                                 output4g = zero_g; \
661                                 output4b = zero_b; \
662                                 if(components == 4) output4a = zero_a; \
663                         } \
664  \
665                         if(in_row2) \
666                         { \
667                                 output3r = in_row2[x * components]; \
668                                 output3g = in_row2[x * components + 1]; \
669                                 output3b = in_row2[x * components + 2]; \
670                                 if(components == 4) output3a = in_row2[x * components + 3]; \
671                         } \
672                         else \
673                         { \
674                                 output3r = zero_r; \
675                                 output3g = zero_g; \
676                                 output3b = zero_b; \
677                                 if(components == 4) output3a = zero_a; \
678                         } \
679  \
680             float anti_a = 1.0F - a; \
681                         float anti_b = 1.0F - b; \
682                         out_row[j * components] =  \
683                                 (type)((anti_a) * (((anti_b) * output1r) +  \
684                                 (b * output2r)) +  \
685                 a * (((anti_b) * output3r) +  \
686                                 (b * output4r))); \
687                         out_row[j * components + 1] =   \
688                                 (type)((anti_a) * (((anti_b) * output1g) +  \
689                                 (b * output2g)) +  \
690                 a * (((anti_b) * output3g) +  \
691                                 (b * output4g))); \
692                         out_row[j * components + 2] =   \
693                                 (type)((anti_a) * (((anti_b) * output1b) +  \
694                                 (b * output2b)) +  \
695                 a * (((anti_b) * output3b) +  \
696                                 (b * output4b))); \
697                         if(components == 4) \
698                                 out_row[j * components + 3] =   \
699                                         (type)((anti_a) * (((anti_b) * output1a) +  \
700                                         (b * output2a)) +  \
701                         a * (((anti_b) * output3a) +  \
702                                         (b * output4a))); \
703                 } \
704         } \
705  \
706  \
707 }
708
709
710 #define BICUBIC(max, type, components) \
711 { \
712         float k_y = 1.0 / scale_h; \
713         float k_x = 1.0 / scale_w; \
714         type **in_rows = (type**)input->get_rows(); \
715         type **out_rows = (type**)output->get_rows(); \
716         float *bspline_x, *bspline_y; \
717         int in_h_int = input->get_h(); \
718         int in_w_int = input->get_w(); \
719         type zero_r, zero_g, zero_b, zero_a; \
720  \
721         zero_r = 0; \
722         zero_b = ((max + 1) >> 1) * (do_yuv); \
723         zero_g = ((max + 1) >> 1) * (do_yuv); \
724         if(components == 4) \
725                 zero_a = 0; \
726  \
727         tabulate_bspline(bspline_x,  \
728                 k_x, \
729                 out_w_int, \
730                 -1); \
731  \
732         tabulate_bspline(bspline_y,  \
733                 k_y, \
734                 out_h_int, \
735                 1); \
736  \
737         for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
738         { \
739                 float f_y = (float)i * k_y; \
740                 int i_y = (int)floor(f_y); \
741                 float a = f_y - floor(f_y); \
742  \
743  \
744                 for(int j = 0; j < out_w_int; j++) \
745                 { \
746                         float f_x = (float)j * k_x; \
747                         int i_x = (int)floor(f_x); \
748                         float b = f_x - floor(f_x); \
749                         float output1, output2, output3, output4; \
750                         output1 = 0; \
751                         output2 = 0; \
752                         output3 = 0; \
753                         if(components == 4) \
754                                 output4 = 0; \
755                         int table_y = i * 4; \
756  \
757 /* Kernel */ \
758                         for(int m = -1; m < 3; m++) \
759                         { \
760                                 float r1 = bspline_y[table_y++]; \
761                                 int y = in_y1_int + i_y + m; \
762                                 int table_x = j * 4; \
763  \
764                                 for(int n = -1; n < 3; n++) \
765                                 { \
766                                         float r2 = bspline_x[table_x++]; \
767                                         int x = in_x1_int + i_x + n; \
768                                         float r_square = r1 * r2; \
769  \
770 /* Inside boundary. */ \
771                                         if(x >= 0 && \
772                                                 x < in_w_int && \
773                                                 y >= 0 && \
774                                                 y < in_h_int) \
775                                         { \
776                                                 output1 += r_square * in_rows[y][x * components]; \
777                                                 output2 += r_square * in_rows[y][x * components + 1]; \
778                                                 output3 += r_square * in_rows[y][x * components + 2]; \
779                                                 if(components == 4) \
780                                                         output4 += r_square * in_rows[y][x * components + 3]; \
781                                         } \
782                                         else \
783                                         { \
784                                                 output1 += r_square * zero_r; \
785                                                 output2 += r_square * zero_g; \
786                                                 output3 += r_square * zero_b; \
787                                                 if(components == 4) \
788                                                         output4 += r_square * zero_a; \
789                                         } \
790                                 } \
791                         } \
792  \
793  \
794                         out_rows[i][j * components] = (type)output1; \
795                         out_rows[i][j * components + 1] = (type)output2; \
796                         out_rows[i][j * components + 2] = (type)output3; \
797                         if(components == 4) \
798                                 out_rows[i][j * components + 3] = (type)output4; \
799  \
800                 } \
801         } \
802  \
803         delete [] bspline_x; \
804         delete [] bspline_y; \
805 }
806
807
808
809 // Pow function is not thread safe in Compaqt C
810 #define CUBE(x) ((x) * (x) * (x))
811
812 float ScaleUnit::cubic_bspline(float x)
813 {
814         float a, b, c, d;
815
816         if((x + 2.0F) <= 0.0F) 
817         {
818         a = 0.0F;
819         }
820         else 
821         {
822         a = CUBE(x + 2.0F);
823         }
824
825
826         if((x + 1.0F) <= 0.0F) 
827         {
828         b = 0.0F;
829         }
830         else 
831         {
832         b = CUBE(x + 1.0F);
833         }    
834
835         if(x <= 0) 
836         {
837         c = 0.0F;
838         }
839         else 
840         {
841         c = CUBE(x);
842         }  
843
844         if((x - 1.0F) <= 0.0F) 
845         {
846         d = 0.0F;
847         }
848         else 
849         {
850         d = CUBE(x - 1.0F);
851         }
852
853         return (a - (4.0F * b) + (6.0F * c) - (4.0F * d)) / 6.0;
854 }
855
856
857 void ScaleUnit::tabulate_bspline(float* &table, 
858         float scale,
859         int pixels,
860         float coefficient)
861 {
862         table = new float[pixels * 4];
863
864         for(int i = 0, j = 0; i < pixels; i++)
865         {
866                 float f_x = (float)i * scale;
867                 float a = f_x - floor(f_x);
868                 
869                 for(float m = -1; m < 3; m++)
870                 {
871                         table[j++] = cubic_bspline(coefficient * (m - a));
872                 }
873         }
874 }
875
876 void ScaleUnit::process_package(LoadPackage *package)
877 {
878         ScalePackage *pkg = (ScalePackage*)package;
879
880 // Arguments for macros
881         VFrame *output = overlay->scale_output;
882         VFrame *input = overlay->scale_input;
883         float scale_w = overlay->w_scale;
884         float scale_h = overlay->h_scale;
885         int in_x1_int = overlay->in_x1_int;
886         int in_y1_int = overlay->in_y1_int;
887         int out_h_int = overlay->out_h_int;
888         int out_w_int = overlay->out_w_int;
889         int do_yuv = 
890                 (overlay->scale_input->get_color_model() == BC_YUV888 ||
891                 overlay->scale_input->get_color_model() == BC_YUVA8888 ||
892                 overlay->scale_input->get_color_model() == BC_YUV161616 ||
893                 overlay->scale_input->get_color_model() == BC_YUVA16161616);
894
895         if(overlay->interpolation_type == CUBIC_CUBIC || 
896                 (overlay->interpolation_type == CUBIC_LINEAR 
897                         && overlay->w_scale > 1 && 
898                         overlay->h_scale > 1))
899         {
900         
901                 switch(overlay->scale_input->get_color_model())
902                 {
903                         case BC_RGB888:
904                         case BC_YUV888:
905                                 BICUBIC(0xff, unsigned char, 3);
906                                 break;
907
908                         case BC_RGBA8888:
909                         case BC_YUVA8888:
910                                 BICUBIC(0xff, unsigned char, 4);
911                                 break;
912
913                         case BC_RGB161616:
914                         case BC_YUV161616:
915                                 BICUBIC(0xffff, uint16_t, 3);
916                                 break;
917
918                         case BC_RGBA16161616:
919                         case BC_YUVA16161616:
920                                 BICUBIC(0xffff, uint16_t, 4);
921                                 break;
922                 }
923         }
924         else
925 // Perform bilinear scaling input -> scale_output
926         {
927                 switch(overlay->scale_input->get_color_model())
928                 {
929                         case BC_RGB888:
930                         case BC_YUV888:
931                                 BILINEAR(0xff, unsigned char, 3);
932                                 break;
933
934                         case BC_RGBA8888:
935                         case BC_YUVA8888:
936                                 BILINEAR(0xff, unsigned char, 4);
937                                 break;
938
939                         case BC_RGB161616:
940                         case BC_YUV161616:
941                                 BILINEAR(0xffff, uint16_t, 3);
942                                 break;
943
944                         case BC_RGBA16161616:
945                         case BC_YUVA16161616:
946                                 BILINEAR(0xffff, uint16_t, 4);
947                                 break;
948                 }
949         }
950
951 }
952
953
954
955
956
957
958
959
960
961
962
963
964
965 ScaleEngine::ScaleEngine(OverlayFrame *overlay, int cpus)
966  : LoadServer(cpus, cpus)
967 {
968         this->overlay = overlay;
969 }
970
971 ScaleEngine::~ScaleEngine()
972 {
973 }
974
975 void ScaleEngine::init_packages()
976 {
977         for(int i = 0; i < total_packages; i++)
978         {
979                 ScalePackage *package = (ScalePackage*)packages[i];
980                 package->out_row1 = overlay->out_h_int / total_packages * i;
981                 package->out_row2 = package->out_row1 + overlay->out_h_int / total_packages;
982
983                 if(i >= total_packages - 1)
984                         package->out_row2 = overlay->out_h_int;
985         }
986 }
987
988 LoadClient* ScaleEngine::new_client()
989 {
990         return new ScaleUnit(this, overlay);
991 }
992
993 LoadPackage* ScaleEngine::new_package()
994 {
995         return new ScalePackage;
996 }
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010 TranslatePackage::TranslatePackage()
1011 {
1012 }
1013
1014
1015
1016 TranslateUnit::TranslateUnit(TranslateEngine *server, OverlayFrame *overlay)
1017  : LoadClient(server)
1018 {
1019         this->overlay = overlay;
1020 }
1021
1022 TranslateUnit::~TranslateUnit()
1023 {
1024 }
1025
1026
1027
1028 void TranslateUnit::translation_array(transfer_table* &table, 
1029         float out_x1, 
1030         float out_x2,
1031         float in_x1,
1032         float in_x2,
1033         int in_total, 
1034         int out_total, 
1035         int &out_x1_int,
1036         int &out_x2_int)
1037 {
1038         int out_w_int;
1039         float offset = out_x1 - in_x1;
1040
1041         out_x1_int = (int)out_x1;
1042         out_x2_int = MIN((int)ceil(out_x2), out_total);
1043         out_w_int = out_x2_int - out_x1_int;
1044
1045         table = new transfer_table[out_w_int];
1046         bzero(table, sizeof(transfer_table) * out_w_int);
1047
1048
1049 //printf("OverlayFrame::translation_array 1 %f %f -> %f %f\n", in_x1, in_x2, out_x1, out_x2);
1050
1051         float in_x = in_x1;
1052         for(int out_x = out_x1_int; out_x < out_x2_int; out_x++)
1053         {
1054                 transfer_table *entry = &table[out_x - out_x1_int];
1055
1056                 entry->in_x1 = (int)in_x;
1057                 entry->in_x2 = (int)in_x + 1;
1058
1059 // Get fraction of output pixel to fill
1060                 entry->output_fraction = 1;
1061
1062                 if(out_x1 > out_x)
1063                 {
1064                         entry->output_fraction -= out_x1 - out_x;
1065                 }
1066
1067                 if(out_x2 < out_x + 1)
1068                 {
1069                         entry->output_fraction = (out_x2 - out_x);
1070                 }
1071
1072 // Advance in_x until out_x_fraction is filled
1073                 float out_x_fraction = entry->output_fraction;
1074                 float in_x_fraction = floor(in_x + 1) - in_x;
1075
1076                 if(out_x_fraction <= in_x_fraction)
1077                 {
1078                         entry->in_fraction1 = out_x_fraction;
1079                         entry->in_fraction2 = 0.0;
1080                         in_x += out_x_fraction;
1081                 }
1082                 else
1083                 {
1084                         entry->in_fraction1 = in_x_fraction;
1085                         in_x += out_x_fraction;
1086                         entry->in_fraction2 = in_x - floor(in_x);
1087                 }
1088
1089 // Clip in_x
1090                 if(entry->in_x2 >= in_total)
1091                 {
1092                         entry->in_x2 = in_total - 1;
1093                         entry->in_fraction2 = 0.0;
1094                 }
1095                 
1096                 if(entry->in_x1 >= in_total)
1097                 {
1098                         entry->in_x1 = in_total - 1;
1099                         entry->in_fraction1 = 0.0;
1100                 }
1101 // printf("OverlayFrame::translation_array 2 %d %d %d %f %f %f\n", 
1102 //      out_x, 
1103 //      entry->in_x1, 
1104 //      entry->in_x2, 
1105 //      entry->in_fraction1, 
1106 //      entry->in_fraction2, 
1107 //      entry->output_fraction);
1108         }
1109 }
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144 #define TRANSLATE(max, type, components) \
1145 { \
1146  \
1147         type **in_rows = (type**)input->get_rows(); \
1148         type **out_rows = (type**)output->get_rows(); \
1149  \
1150 /* printf("OverlayFrame::translate 1  %.2f %.2f %.2f %.2f -> %.2f %.2f %.2f %.2f\n",  */ \
1151 /*      (in_x1),  in_y1,  in_x2,  in_y2,  out_x1,  out_y1, out_x2,  out_y2); */ \
1152  \
1153         unsigned int master_opacity = (int)(alpha * max + 0.5); \
1154         unsigned int master_transparency = max - master_opacity; \
1155  \
1156 /* printf("TRANSLATE %d\n", mode); */ \
1157  \
1158         for(int i = row1; i < row2; i++) \
1159         { \
1160                 int in_y1 = y_table[i - out_y1_int].in_x1; \
1161                 int in_y2 = y_table[i - out_y1_int].in_x2; \
1162                 float y_fraction1 = y_table[i - out_y1_int].in_fraction1; \
1163                 float y_fraction2 = y_table[i - out_y1_int].in_fraction2; \
1164                 float y_output_fraction = y_table[i - out_y1_int].output_fraction; \
1165                 type *in_row1 = in_rows[(in_y1)]; \
1166                 type *in_row2 = in_rows[(in_y2)]; \
1167                 type *out_row = out_rows[i]; \
1168  \
1169                 for(int j = out_x1_int; j < out_x2_int; j++) \
1170                 { \
1171                         int in_x1 = x_table[j - out_x1_int].in_x1; \
1172                         int in_x2 = x_table[j - out_x1_int].in_x2; \
1173                         float x_fraction1 = x_table[j - out_x1_int].in_fraction1; \
1174                         float x_fraction2 = x_table[j - out_x1_int].in_fraction2; \
1175                         float x_output_fraction = x_table[j - out_x1_int].output_fraction; \
1176                         type *output = &out_row[j * components]; \
1177                         int input1, input2, input3, input4; \
1178  \
1179                         input1 = (int)(in_row1[in_x1 * components] * x_fraction1 * y_fraction1 +  \
1180                                 in_row1[in_x2 * components] * x_fraction2 * y_fraction1 +  \
1181                                 in_row2[in_x1 * components] * x_fraction1 * y_fraction2 +  \
1182                                 in_row2[in_x2 * components] * x_fraction2 * y_fraction2 + 0.5); \
1183                         input2 = (int)(in_row1[in_x1 * components + 1] * x_fraction1 * y_fraction1 +  \
1184                                 in_row1[in_x2 * components + 1] * x_fraction2 * y_fraction1 +  \
1185                                 in_row2[in_x1 * components + 1] * x_fraction1 * y_fraction2 +  \
1186                                 in_row2[in_x2 * components + 1] * x_fraction2 * y_fraction2 + 0.5); \
1187                         input3 = (int)(in_row1[in_x1 * components + 2] * x_fraction1 * y_fraction1 +  \
1188                                 in_row1[in_x2 * components + 2] * x_fraction2 * y_fraction1 +  \
1189                                 in_row2[in_x1 * components + 2] * x_fraction1 * y_fraction2 +  \
1190                                 in_row2[in_x2 * components + 2] * x_fraction2 * y_fraction2 + 0.5); \
1191                         if(components == 4) \
1192                                 input4 = (int)(in_row1[in_x1 * components + 3] * x_fraction1 * y_fraction1 +  \
1193                                         in_row1[in_x2 * components + 3] * x_fraction2 * y_fraction1 +  \
1194                                         in_row2[in_x1 * components + 3] * x_fraction1 * y_fraction2 +  \
1195                                         in_row2[in_x2 * components + 3] * x_fraction2 * y_fraction2 + 0.5); \
1196  \
1197                         unsigned int opacity = (int)(master_opacity *  \
1198                                 y_output_fraction *  \
1199                                 x_output_fraction + 0.5); \
1200                         unsigned int transparency = max - opacity; \
1201  \
1202 /* if(opacity != max) printf("TRANSLATE %x %d %d\n", opacity, j, i); */ \
1203  \
1204                         if(components == 3) \
1205                         { \
1206                                 BLEND_3(max, type); \
1207                         } \
1208                         else \
1209                         { \
1210                                 BLEND_4(max, type); \
1211                         } \
1212                 } \
1213         } \
1214 }
1215
1216 void TranslateUnit::process_package(LoadPackage *package)
1217 {
1218         TranslatePackage *pkg = (TranslatePackage*)package;
1219         int out_y1_int; 
1220         int out_y2_int; 
1221         int out_x1_int; 
1222         int out_x2_int; 
1223
1224
1225 // Variables for TRANSLATE
1226         VFrame *input = overlay->translate_input;
1227         VFrame *output = overlay->translate_output;
1228         float in_x1 = overlay->translate_in_x1;
1229         float in_y1 = overlay->translate_in_y1;
1230         float in_x2 = overlay->translate_in_x2;
1231         float in_y2 = overlay->translate_in_y2;
1232         float out_x1 = overlay->translate_out_x1;
1233         float out_y1 = overlay->translate_out_y1;
1234         float out_x2 = overlay->translate_out_x2;
1235         float out_y2 = overlay->translate_out_y2;
1236         float alpha = overlay->translate_alpha;
1237         int row1 = pkg->out_row1;
1238         int row2 = pkg->out_row2;
1239         int mode = overlay->translate_mode;
1240
1241         transfer_table *x_table; 
1242         transfer_table *y_table; 
1243  
1244         translation_array(x_table,  
1245                 out_x1,  
1246                 out_x2, 
1247                 in_x1, 
1248                 in_x2, 
1249                 input->get_w(),  
1250                 output->get_w(),  
1251                 out_x1_int, 
1252                 out_x2_int); 
1253         translation_array(y_table,  
1254                 out_y1,  
1255                 out_y2, 
1256                 in_y1, 
1257                 in_y2, 
1258                 input->get_h(),  
1259                 output->get_h(),  
1260                 out_y1_int, 
1261                 out_y2_int); 
1262  
1263         switch(overlay->translate_input->get_color_model())
1264         {
1265                 case BC_RGB888:
1266                 case BC_YUV888:
1267                         TRANSLATE(0xff, unsigned char, 3);
1268                         break;
1269
1270                 case BC_RGBA8888:
1271                 case BC_YUVA8888:
1272                         TRANSLATE(0xff, unsigned char, 4);
1273                         break;
1274
1275                 case BC_RGB161616:
1276                 case BC_YUV161616:
1277                         TRANSLATE(0xffff, uint16_t, 3);
1278                         break;
1279
1280                 case BC_RGBA16161616:
1281                 case BC_YUVA16161616:
1282                         TRANSLATE(0xffff, uint16_t, 4);
1283                         break;
1284         }
1285  
1286         delete [] x_table; 
1287         delete [] y_table; 
1288 }
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299 TranslateEngine::TranslateEngine(OverlayFrame *overlay, int cpus)
1300  : LoadServer(cpus, cpus)
1301 {
1302         this->overlay = overlay;
1303 }
1304
1305 TranslateEngine::~TranslateEngine()
1306 {
1307 }
1308
1309 void TranslateEngine::init_packages()
1310 {
1311         int out_y1_int = (int)overlay->translate_out_y1;
1312         int out_y2_int = MIN((int)ceil(overlay->translate_out_y2), overlay->translate_output->get_h());
1313         int out_h = out_y2_int - out_y1_int;
1314
1315         for(int i = 0; i < total_packages; i++)
1316         {
1317                 TranslatePackage *package = (TranslatePackage*)packages[i];
1318                 package->out_row1 = (int)(out_y1_int + out_h / 
1319                         total_packages * 
1320                         i);
1321                 package->out_row2 = (int)((float)package->out_row1 + 
1322                         out_h / 
1323                         total_packages);
1324                 if(i >= total_packages - 1)
1325                         package->out_row2 = out_y2_int;
1326         }
1327 }
1328
1329 LoadClient* TranslateEngine::new_client()
1330 {
1331         return new TranslateUnit(this, overlay);
1332 }
1333
1334 LoadPackage* TranslateEngine::new_package()
1335 {
1336         return new TranslatePackage;
1337 }
1338
1339
1340
1341
1342
1343
1344
1345
1346 #define SCALE_TRANSLATE(max, type, components) \
1347 { \
1348         int64_t opacity = (int)(alpha * max + 0.5); \
1349         int64_t transparency = max - opacity; \
1350         int out_w = out_x2 - out_x1; \
1351  \
1352         for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
1353         { \
1354                 int in_y = y_table[i - out_y1]; \
1355                 type *in_row = (type*)in_rows[in_y] + in_x1 * components; \
1356                 type *out_row = (type*)out_rows[i] + out_x1 * components; \
1357  \
1358 /* X direction is scaled and requires a table lookup */ \
1359                 if(out_w != in_x2 - in_x1) \
1360                 { \
1361                         for(int j = 0; j < out_w; j++) \
1362                         { \
1363                                 int in_x = x_table[j]; \
1364                                 int input1, input2, input3, input4; \
1365                                 type *output = out_row + j * components; \
1366          \
1367                                 input1 = in_row[in_x * components]; \
1368                                 input2 = in_row[in_x * components + 1]; \
1369                                 input3 = in_row[in_x * components + 2]; \
1370                                 if(components == 4) \
1371                                         input4 = in_row[in_x * components + 3]; \
1372          \
1373                                 if(components == 3) \
1374                                 { \
1375                                         BLEND_3(max, type); \
1376                                 } \
1377                                 else \
1378                                 { \
1379                                         BLEND_4(max, type); \
1380                                 } \
1381                         } \
1382                 } \
1383                 else \
1384 /* X direction is not scaled */ \
1385                 { \
1386                         for(int j = 0; j < out_w; j++) \
1387                         { \
1388                                 int input1, input2, input3, input4; \
1389                                 type *output = out_row + j * components; \
1390          \
1391                                 input1 = in_row[j * components]; \
1392                                 input2 = in_row[j * components + 1]; \
1393                                 input3 = in_row[j * components + 2]; \
1394                                 if(components == 4) \
1395                                         input4 = in_row[j * components + 3]; \
1396          \
1397                                 if(components == 3) \
1398                                 { \
1399                                         BLEND_3(max, type); \
1400                                 } \
1401                                 else \
1402                                 { \
1403                                         BLEND_4(max, type); \
1404                                 } \
1405                         } \
1406                 } \
1407         } \
1408 }
1409
1410
1411
1412 ScaleTranslateUnit::ScaleTranslateUnit(ScaleTranslateEngine *server, OverlayFrame *overlay)
1413  : LoadClient(server)
1414 {
1415         this->overlay = overlay;
1416         this->scale_translate = server;
1417 }
1418
1419 ScaleTranslateUnit::~ScaleTranslateUnit()
1420 {
1421 }
1422
1423 void ScaleTranslateUnit::scale_array(int* &table, 
1424         int out_x1, 
1425         int out_x2,
1426         int in_x1,
1427         int in_x2,
1428         int is_x)
1429 {
1430         float scale = (float)(out_x2 - out_x1) / (in_x2 - in_x1);
1431
1432         table = new int[out_x2 - out_x1];
1433         
1434         if(!is_x)
1435         {
1436                 for(int i = 0; i < out_x2 - out_x1; i++)
1437                 {
1438                         table[i] = (int)((float)i / scale + in_x1);
1439                 }
1440         }
1441         else
1442         {       
1443                 for(int i = 0; i < out_x2 - out_x1; i++)
1444                 {
1445                         table[i] = (int)((float)i / scale);
1446                 }
1447         }
1448 }
1449
1450
1451 void ScaleTranslateUnit::process_package(LoadPackage *package)
1452 {
1453         ScaleTranslatePackage *pkg = (ScaleTranslatePackage*)package;
1454
1455 // Args for NEAREST_NEIGHBOR_MACRO
1456         VFrame *output = scale_translate->output;
1457         VFrame *input = scale_translate->input;
1458         int in_x1 = scale_translate->in_x1;
1459         int in_y1 = scale_translate->in_y1;
1460         int in_x2 = scale_translate->in_x2;
1461         int in_y2 = scale_translate->in_y2;
1462         int out_x1 = scale_translate->out_x1;
1463         int out_y1 = scale_translate->out_y1;
1464         int out_x2 = scale_translate->out_x2;
1465         int out_y2 = scale_translate->out_y2;
1466         float alpha = scale_translate->alpha;
1467         int mode = scale_translate->mode;
1468
1469         int *x_table;
1470         int *y_table;
1471         unsigned char **in_rows = input->get_rows();
1472         unsigned char **out_rows = output->get_rows();
1473
1474         scale_array(x_table, 
1475                 out_x1, 
1476                 out_x2,
1477                 in_x1,
1478                 in_x2,
1479                 1);
1480         scale_array(y_table, 
1481                 out_y1, 
1482                 out_y2,
1483                 in_y1,
1484                 in_y2,
1485                 0);
1486
1487
1488         switch(input->get_color_model())
1489         {
1490                 case BC_RGB888:
1491                 case BC_YUV888:
1492                         SCALE_TRANSLATE(0xff, uint8_t, 3);
1493                         break;
1494
1495                 case BC_RGBA8888:
1496                 case BC_YUVA8888:
1497                         SCALE_TRANSLATE(0xff, uint8_t, 4);
1498                         break;
1499
1500
1501                 case BC_RGB161616:
1502                 case BC_YUV161616:
1503                         SCALE_TRANSLATE(0xffff, uint16_t, 3);
1504                         break;
1505
1506                 case BC_RGBA16161616:
1507                 case BC_YUVA16161616:
1508                         SCALE_TRANSLATE(0xffff, uint16_t, 4);
1509                         break;
1510         }
1511         
1512         delete [] x_table;
1513         delete [] y_table;
1514
1515 };
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525 ScaleTranslateEngine::ScaleTranslateEngine(OverlayFrame *overlay, int cpus)
1526  : LoadServer(cpus, cpus)
1527 {
1528         this->overlay = overlay;
1529 }
1530
1531 ScaleTranslateEngine::~ScaleTranslateEngine()
1532 {
1533 }
1534
1535 void ScaleTranslateEngine::init_packages()
1536 {
1537         int out_h = out_y2 - out_y1;
1538
1539         for(int i = 0; i < total_packages; i++)
1540         {
1541                 ScaleTranslatePackage *package = (ScaleTranslatePackage*)packages[i];
1542                 package->out_row1 = (int)(out_y1 + out_h / 
1543                         total_packages * 
1544                         i);
1545                 package->out_row2 = (int)((float)package->out_row1 + 
1546                         out_h / 
1547                         total_packages);
1548                 if(i >= total_packages - 1)
1549                         package->out_row2 = out_y2;
1550         }
1551 }
1552
1553 LoadClient* ScaleTranslateEngine::new_client()
1554 {
1555         return new ScaleTranslateUnit(this, overlay);
1556 }
1557
1558 LoadPackage* ScaleTranslateEngine::new_package()
1559 {
1560         return new ScaleTranslatePackage;
1561 }
1562
1563
1564 ScaleTranslatePackage::ScaleTranslatePackage()
1565 {
1566 }
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595 #define BLEND_ONLY(type, max, components) \
1596 { \
1597         int64_t opacity = (int)(alpha * max + 0.5); \
1598         int64_t transparency = max - opacity; \
1599  \
1600         type** output_rows = (type**)output->get_rows(); \
1601         type** input_rows = (type**)input->get_rows(); \
1602         int w = input->get_w(); \
1603         int h = input->get_h(); \
1604  \
1605         for(int i = pkg->out_row1; i < pkg->out_row2; i++) \
1606         { \
1607                 type* in_row = input_rows[i]; \
1608                 type* output = output_rows[i]; \
1609  \
1610                 for(int j = 0; j < w; j++) \
1611                 { \
1612                         int input1, input2, input3, input4; \
1613                         input1 = in_row[j * components]; \
1614                         input2 = in_row[j * components + 1]; \
1615                         input3 = in_row[j * components + 2]; \
1616                         if(components == 4) input4 = in_row[j * components + 3]; \
1617  \
1618  \
1619                         if(components == 3) \
1620                         { \
1621                                 BLEND_3(max, type); \
1622                         } \
1623                         else \
1624                         { \
1625                                 BLEND_4(max, type); \
1626                         } \
1627  \
1628                         input += components; \
1629                         output += components; \
1630                 } \
1631         } \
1632 }
1633
1634
1635
1636
1637 BlendUnit::BlendUnit(BlendEngine *server, OverlayFrame *overlay)
1638  : LoadClient(server)
1639 {
1640         this->overlay = overlay;
1641         this->blend_engine = server;
1642 }
1643
1644 BlendUnit::~BlendUnit()
1645 {
1646 }
1647
1648 void BlendUnit::process_package(LoadPackage *package)
1649 {
1650         BlendPackage *pkg = (BlendPackage*)package;
1651
1652
1653         VFrame *output = blend_engine->output;
1654         VFrame *input = blend_engine->input;
1655         float alpha = blend_engine->alpha;
1656         int mode = blend_engine->mode;
1657
1658         switch(input->get_color_model())
1659         {
1660                 case BC_RGB888:
1661                 case BC_YUV888:
1662                         BLEND_ONLY(unsigned char, 0xff, 3);
1663                         break;
1664                 case BC_RGBA8888:
1665                 case BC_YUVA8888:
1666                         BLEND_ONLY(unsigned char, 0xff, 4);
1667                         break;
1668                 case BC_RGB161616:
1669                 case BC_YUV161616:
1670                         BLEND_ONLY(uint16_t, 0xffff, 3);
1671                         break;
1672                 case BC_RGBA16161616:
1673                 case BC_YUVA16161616:
1674                         BLEND_ONLY(uint16_t, 0xffff, 4);
1675                         break;
1676         }
1677 }
1678
1679
1680
1681 BlendEngine::BlendEngine(OverlayFrame *overlay, int cpus)
1682  : LoadServer(cpus, cpus)
1683 {
1684         this->overlay = overlay;
1685 }
1686
1687 BlendEngine::~BlendEngine()
1688 {
1689 }
1690
1691 void BlendEngine::init_packages()
1692 {
1693         for(int i = 0; i < total_packages; i++)
1694         {
1695                 BlendPackage *package = (BlendPackage*)packages[i];
1696                 package->out_row1 = (int)(input->get_h() / 
1697                         total_packages * 
1698                         i);
1699                 package->out_row2 = (int)((float)package->out_row1 +
1700                         input->get_h() / 
1701                         total_packages);
1702
1703                 if(i >= total_packages - 1)
1704                         package->out_row2 = input->get_h();
1705         }
1706 }
1707
1708 LoadClient* BlendEngine::new_client()
1709 {
1710         return new BlendUnit(this, overlay);
1711 }
1712
1713 LoadPackage* BlendEngine::new_package()
1714 {
1715         return new BlendPackage;
1716 }
1717
1718
1719 BlendPackage::BlendPackage()
1720 {
1721 }
1722
1723