r105: This commit was manufactured by cvs2svn to create tag
[cinelerra_cv/mob.git] / hvirtual / cinelerra / overlayframe.C.float
blob24c77812a48509a90f4c7c3e53082774ef933107
1 #include <math.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdint.h>
6 #include "clip.h"
7 #include "edl.inc"
8 #include "overlayframe.h"
9 #include "vframe.h"
11 OverlayFrame::OverlayFrame(int cpus)
13         temp_frame = 0;
14         blend_engine = 0;
15         scale_engine = 0;
16         scaletranslate_engine = 0;
17         translate_engine = 0;
18         this->cpus = cpus;
21 OverlayFrame::~OverlayFrame()
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");
39 // Verification: 
41 // (255 * 255 + 0 * 0) / 255 = 255
42 // (255 * 127 + 255 * (255 - 127)) / 255 = 255
44 // (65535 * 65535 + 0 * 0) / 65535 = 65535
45 // (65535 * 32767 + 65535 * (65535 - 32767)) / 65535 = 65535
48 // Branch prediction 4 U
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); \
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; \
110         pixel_opacity = opacity * input4 / max; \
111         pixel_transparency = (max - pixel_opacity) * output[3] / max; \
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         } \
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; \
172 // Bicubic algorithm using multiprocessors
173 // input -> scale nearest integer boundaries -> temp -> translation -> blend -> output
175 // Nearest neighbor algorithm using multiprocessors for blending
176 // input -> scale + translate -> blend -> output
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)
193         float w_scale = (out_x2 - out_x1) / (in_x2 - in_x1);
194         float h_scale = (out_y2 - out_y1) / (in_y2 - in_y1);
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         }
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         }
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         }
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         }
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         }
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         }
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         }
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         }
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;
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);
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());
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;
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))
350 #define NO_BLEND \
351         (EQUIV(alpha, 1) && \
352         (mode == TRANSFER_REPLACE || \
353         (mode == TRANSFER_NORMAL && cmodel_components(input->get_color_model()) == 3)))
359 // Prepare destination for operation
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");
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                         }
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");
395                         temp_frame->clear_frame();
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;
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                 }
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;
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");
430         }
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);
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())) \
456 #define NO_SCALE \
457         (EQUIV(out_x2 - out_x1, in_x2 - in_x1) && \
458         EQUIV(out_y2 - out_y1, in_y2 - in_y1))
460         
463 //printf("OverlayFrame::overlay 4 %d\n", mode);
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);
486                         blend_engine->output = output;
487                         blend_engine->input = translation_input;
488                         blend_engine->alpha = alpha;
489                         blend_engine->mode = mode;
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) &&
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);
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;
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;
552 //printf("OverlayFrame::overlay 5 %d\n", mode);
553                         if(!translate_engine) translate_engine = new TranslateEngine(this, cpus);
554                         translate_engine->process_packages();
556                 }
557         }
558 //printf("OverlayFrame::overlay 2\n");
560         return 0;
569 ScalePackage::ScalePackage()
576 ScaleUnit::ScaleUnit(ScaleEngine *server, OverlayFrame *overlay)
577  : LoadClient(server)
579         this->overlay = overlay;
582 ScaleUnit::~ScaleUnit()
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(); \
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; \
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]; \
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; \
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]; \
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]; \
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                         } \
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                         } \
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         } \
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; \
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; \
727         tabulate_bspline(bspline_x,  \
728                 k_x, \
729                 out_w_int, \
730                 -1); \
732         tabulate_bspline(bspline_y,  \
733                 k_y, \
734                 out_h_int, \
735                 1); \
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); \
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; \
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; \
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; \
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                         } \
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; \
800                 } \
801         } \
803         delete [] bspline_x; \
804         delete [] bspline_y; \
809 // Pow function is not thread safe in Compaqt C
810 #define CUBE(x) ((x) * (x) * (x))
812 float ScaleUnit::cubic_bspline(float x)
814         float a, b, c, d;
816         if((x + 2.0F) <= 0.0F) 
817         {
818         a = 0.0F;
819         }
820         else 
821         {
822         a = CUBE(x + 2.0F);
823         }
826         if((x + 1.0F) <= 0.0F) 
827         {
828         b = 0.0F;
829         }
830         else 
831         {
832         b = CUBE(x + 1.0F);
833         }    
835         if(x <= 0) 
836         {
837         c = 0.0F;
838         }
839         else 
840         {
841         c = CUBE(x);
842         }  
844         if((x - 1.0F) <= 0.0F) 
845         {
846         d = 0.0F;
847         }
848         else 
849         {
850         d = CUBE(x - 1.0F);
851         }
853         return (a - (4.0F * b) + (6.0F * c) - (4.0F * d)) / 6.0;
857 void ScaleUnit::tabulate_bspline(float* &table, 
858         float scale,
859         int pixels,
860         float coefficient)
862         table = new float[pixels * 4];
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         }
876 void ScaleUnit::process_package(LoadPackage *package)
878         ScalePackage *pkg = (ScalePackage*)package;
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);
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;
908                         case BC_RGBA8888:
909                         case BC_YUVA8888:
910                                 BICUBIC(0xff, unsigned char, 4);
911                                 break;
913                         case BC_RGB161616:
914                         case BC_YUV161616:
915                                 BICUBIC(0xffff, uint16_t, 3);
916                                 break;
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;
934                         case BC_RGBA8888:
935                         case BC_YUVA8888:
936                                 BILINEAR(0xff, unsigned char, 4);
937                                 break;
939                         case BC_RGB161616:
940                         case BC_YUV161616:
941                                 BILINEAR(0xffff, uint16_t, 3);
942                                 break;
944                         case BC_RGBA16161616:
945                         case BC_YUVA16161616:
946                                 BILINEAR(0xffff, uint16_t, 4);
947                                 break;
948                 }
949         }
965 ScaleEngine::ScaleEngine(OverlayFrame *overlay, int cpus)
966  : LoadServer(cpus, cpus)
968         this->overlay = overlay;
971 ScaleEngine::~ScaleEngine()
975 void ScaleEngine::init_packages()
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;
983                 if(i >= total_packages - 1)
984                         package->out_row2 = overlay->out_h_int;
985         }
988 LoadClient* ScaleEngine::new_client()
990         return new ScaleUnit(this, overlay);
993 LoadPackage* ScaleEngine::new_package()
995         return new ScalePackage;
1010 TranslatePackage::TranslatePackage()
1016 TranslateUnit::TranslateUnit(TranslateEngine *server, OverlayFrame *overlay)
1017  : LoadClient(server)
1019         this->overlay = overlay;
1022 TranslateUnit::~TranslateUnit()
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)
1038         int out_w_int;
1039         float offset = out_x1 - in_x1;
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;
1045         table = new transfer_table[out_w_int];
1046         bzero(table, sizeof(transfer_table) * out_w_int);
1049 //printf("OverlayFrame::translation_array 1 %f %f -> %f %f\n", in_x1, in_x2, out_x1, out_x2);
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];
1056                 entry->in_x1 = (int)in_x;
1057                 entry->in_x2 = (int)in_x + 1;
1059 // Get fraction of output pixel to fill
1060                 entry->output_fraction = 1;
1062                 if(out_x1 > out_x)
1063                 {
1064                         entry->output_fraction -= out_x1 - out_x;
1065                 }
1067                 if(out_x2 < out_x + 1)
1068                 {
1069                         entry->output_fraction = (out_x2 - out_x);
1070                 }
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;
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                 }
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         }
1144 #define TRANSLATE(max, type, components) \
1145 { \
1147         type **in_rows = (type**)input->get_rows(); \
1148         type **out_rows = (type**)output->get_rows(); \
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); */ \
1153         unsigned int master_opacity = (int)(alpha * max + 0.5); \
1154         unsigned int master_transparency = max - master_opacity; \
1156 /* printf("TRANSLATE %d\n", mode); */ \
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]; \
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; \
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); \
1197                         unsigned int opacity = (int)(master_opacity *  \
1198                                 y_output_fraction *  \
1199                                 x_output_fraction + 0.5); \
1200                         unsigned int transparency = max - opacity; \
1202 /* if(opacity != max) printf("TRANSLATE %x %d %d\n", opacity, j, i); */ \
1204                         if(components == 3) \
1205                         { \
1206                                 BLEND_3(max, type); \
1207                         } \
1208                         else \
1209                         { \
1210                                 BLEND_4(max, type); \
1211                         } \
1212                 } \
1213         } \
1216 void TranslateUnit::process_package(LoadPackage *package)
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; 
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;
1241         transfer_table *x_table; 
1242         transfer_table *y_table; 
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); 
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;
1270                 case BC_RGBA8888:
1271                 case BC_YUVA8888:
1272                         TRANSLATE(0xff, unsigned char, 4);
1273                         break;
1275                 case BC_RGB161616:
1276                 case BC_YUV161616:
1277                         TRANSLATE(0xffff, uint16_t, 3);
1278                         break;
1280                 case BC_RGBA16161616:
1281                 case BC_YUVA16161616:
1282                         TRANSLATE(0xffff, uint16_t, 4);
1283                         break;
1284         }
1286         delete [] x_table; 
1287         delete [] y_table; 
1299 TranslateEngine::TranslateEngine(OverlayFrame *overlay, int cpus)
1300  : LoadServer(cpus, cpus)
1302         this->overlay = overlay;
1305 TranslateEngine::~TranslateEngine()
1309 void TranslateEngine::init_packages()
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;
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         }
1329 LoadClient* TranslateEngine::new_client()
1331         return new TranslateUnit(this, overlay);
1334 LoadPackage* TranslateEngine::new_package()
1336         return new TranslatePackage;
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; \
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; \
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         } \
1412 ScaleTranslateUnit::ScaleTranslateUnit(ScaleTranslateEngine *server, OverlayFrame *overlay)
1413  : LoadClient(server)
1415         this->overlay = overlay;
1416         this->scale_translate = server;
1419 ScaleTranslateUnit::~ScaleTranslateUnit()
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)
1430         float scale = (float)(out_x2 - out_x1) / (in_x2 - in_x1);
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         }
1451 void ScaleTranslateUnit::process_package(LoadPackage *package)
1453         ScaleTranslatePackage *pkg = (ScaleTranslatePackage*)package;
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;
1469         int *x_table;
1470         int *y_table;
1471         unsigned char **in_rows = input->get_rows();
1472         unsigned char **out_rows = output->get_rows();
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);
1488         switch(input->get_color_model())
1489         {
1490                 case BC_RGB888:
1491                 case BC_YUV888:
1492                         SCALE_TRANSLATE(0xff, uint8_t, 3);
1493                         break;
1495                 case BC_RGBA8888:
1496                 case BC_YUVA8888:
1497                         SCALE_TRANSLATE(0xff, uint8_t, 4);
1498                         break;
1501                 case BC_RGB161616:
1502                 case BC_YUV161616:
1503                         SCALE_TRANSLATE(0xffff, uint16_t, 3);
1504                         break;
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;
1525 ScaleTranslateEngine::ScaleTranslateEngine(OverlayFrame *overlay, int cpus)
1526  : LoadServer(cpus, cpus)
1528         this->overlay = overlay;
1531 ScaleTranslateEngine::~ScaleTranslateEngine()
1535 void ScaleTranslateEngine::init_packages()
1537         int out_h = out_y2 - out_y1;
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         }
1553 LoadClient* ScaleTranslateEngine::new_client()
1555         return new ScaleTranslateUnit(this, overlay);
1558 LoadPackage* ScaleTranslateEngine::new_package()
1560         return new ScaleTranslatePackage;
1564 ScaleTranslatePackage::ScaleTranslatePackage()
1595 #define BLEND_ONLY(type, max, components) \
1596 { \
1597         int64_t opacity = (int)(alpha * max + 0.5); \
1598         int64_t transparency = max - opacity; \
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(); \
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]; \
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]; \
1619                         if(components == 3) \
1620                         { \
1621                                 BLEND_3(max, type); \
1622                         } \
1623                         else \
1624                         { \
1625                                 BLEND_4(max, type); \
1626                         } \
1628                         input += components; \
1629                         output += components; \
1630                 } \
1631         } \
1637 BlendUnit::BlendUnit(BlendEngine *server, OverlayFrame *overlay)
1638  : LoadClient(server)
1640         this->overlay = overlay;
1641         this->blend_engine = server;
1644 BlendUnit::~BlendUnit()
1648 void BlendUnit::process_package(LoadPackage *package)
1650         BlendPackage *pkg = (BlendPackage*)package;
1653         VFrame *output = blend_engine->output;
1654         VFrame *input = blend_engine->input;
1655         float alpha = blend_engine->alpha;
1656         int mode = blend_engine->mode;
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         }
1681 BlendEngine::BlendEngine(OverlayFrame *overlay, int cpus)
1682  : LoadServer(cpus, cpus)
1684         this->overlay = overlay;
1687 BlendEngine::~BlendEngine()
1691 void BlendEngine::init_packages()
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);
1703                 if(i >= total_packages - 1)
1704                         package->out_row2 = input->get_h();
1705         }
1708 LoadClient* BlendEngine::new_client()
1710         return new BlendUnit(this, overlay);
1713 LoadPackage* BlendEngine::new_package()
1715         return new BlendPackage;
1719 BlendPackage::BlendPackage()