fixes for checkin 2 times ago
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / overlaysample.C
1 #include "overlayframe.h"
2 #include "overlaysample.h"
3
4 /* Fully resampled scale / translate / blend ******************************/
5 /* resample into a temporary row vector, then blend */
6
7 SamplePackage::SamplePackage()
8 {
9 }
10
11 SampleUnit::SampleUnit(SampleEngine *server)
12  : LoadClient(server)
13 {
14         this->engine = server;
15 }
16
17 SampleUnit::~SampleUnit()
18 {
19 }
20
21 void SampleUnit::process_package(LoadPackage *package)
22 {
23         pkg = (SamplePackage*)package;
24
25         float i1  = engine->in1;
26         float i2  = engine->in2;
27         float o1  = engine->out1;
28         float o2  = engine->out2;
29
30         if(i2 - i1 <= 0 || o2 - o1 <= 0)
31                 return;
32
33         voutput = engine->output;
34         vinput = engine->input;
35         mode = engine->mode;
36         fade = BC_CModels::has_alpha(vinput->get_color_model()) &&
37                 mode == TRANSFER_REPLACE ? 1.f : engine->alpha;
38
39         //iw  = vinput->get_w();
40         i1i = floor(i1);
41         i2i = ceil(i2);
42         i1f = 1.f - i1 + i1i;
43         i2f = 1.f - i2i + i2;
44
45         o1i = floor(o1);
46         o2i = ceil(o2);
47         o1f = 1.f - o1 + o1i;
48         o2f = 1.f - o2i + o2;
49         oh  = o2i - o1i;
50
51         k  = engine->kernel->lookup;
52         //kw  = engine->kernel->width;
53         //kn  = engine->kernel->n;
54         kd = engine->kd;
55
56         lookup_sx0 = engine->lookup_sx0;
57         lookup_sx1 = engine->lookup_sx1;
58         lookup_sk = engine->lookup_sk;
59         lookup_wacc = engine->lookup_wacc;
60
61         switch( vinput->get_color_model() ) {
62         case BC_RGB_FLOAT:      rgb_float();    break;
63         case BC_RGBA_FLOAT:     rgba_float();   break;
64         case BC_RGB888:         rgb888();       break;
65         case BC_YUV888:         yuv888();       break;
66         case BC_RGBA8888:       rgba8888();     break;
67         case BC_YUVA8888:       yuva8888();     break;
68         case BC_RGB161616:      rgb161616();    break;
69         case BC_YUV161616:      yuv161616();    break;
70         case BC_RGBA16161616:   rgba16161616(); break;
71         case BC_YUVA16161616:   yuva16161616();  break;
72         }
73 }
74
75
76 SampleEngine::SampleEngine(int cpus)
77  : LoadServer(cpus, cpus)
78 {
79         lookup_sx0 = 0;
80         lookup_sx1 = 0;
81         lookup_sk = 0;
82         lookup_wacc = 0;
83         kd = 0;
84 }
85
86 SampleEngine::~SampleEngine()
87 {
88         if(lookup_sx0) delete [] lookup_sx0;
89         if(lookup_sx1) delete [] lookup_sx1;
90         if(lookup_sk) delete [] lookup_sk;
91         if(lookup_wacc) delete [] lookup_wacc;
92 }
93
94 /*
95  * unlike the Direct and NN engines, the Sample engine works across
96  * output columns (it makes for more economical memory addressing
97  * during convolution)
98  */
99 void SampleEngine::init_packages()
100 {
101         int   iw  = input->get_w();
102         int   i1i = floor(in1);
103         int   i2i = ceil(in2);
104         float i1f = 1.f - in1 + i1i;
105         float i2f = 1.f - i2i + in2;
106
107         int   oy  = floor(out1);
108         float oyf = out1 - oy;
109         int   oh  = ceil(out2) - oy;
110
111         float *k  = kernel->lookup;
112         float kw  = kernel->width;
113         int   kn  = kernel->n;
114
115         if(in2 - in1 <= 0 || out2 - out1 <= 0)
116                 return;
117
118         /* determine kernel spatial coverage */
119         float scale = (out2 - out1) / (in2 - in1);
120         float iscale = (in2 - in1) / (out2 - out1);
121         float coverage = fabs(1.f / scale);
122         float bound = (coverage < 1.f ? kw : kw * coverage) - (.5f / TRANSFORM_SPP);
123         float coeff = (coverage < 1.f ? 1.f : scale) * TRANSFORM_SPP;
124
125         delete [] lookup_sx0;
126         delete [] lookup_sx1;
127         delete [] lookup_sk;
128         delete [] lookup_wacc;
129
130         lookup_sx0 = new int[oh];
131         lookup_sx1 = new int[oh];
132         lookup_sk = new int[oh];
133         lookup_wacc = new float[oh];
134
135         kd = (double)coeff * (1 << INDEX_FRACTION) + .5;
136
137         /* precompute kernel values and weight sums */
138         for(int i = 0; i < oh; i++) {
139                 /* map destination back to source */
140                 double sx = (i - oyf + .5) * iscale + in1 - .5;
141
142                 /*
143                  * clip iteration to source area but not source plane. Points
144                  * outside the source plane count as transparent. Points outside
145                  * the source area don't count at all.  The actual convolution
146                  * later will be clipped to both, but we need to compute
147                  * weights.
148                  */
149                 int sx0 = mmax((int)floor(sx - bound) + 1, i1i);
150                 int sx1 = mmin((int)ceil(sx + bound), i2i);
151                 int ki = (double)(sx0 - sx) * coeff * (1 << INDEX_FRACTION)
152                                 + (1 << (INDEX_FRACTION - 1)) + .5;
153                 float wacc=0.;
154
155                 lookup_sx0[i] = -1;
156                 lookup_sx1[i] = -1;
157
158                 for(int j= sx0; j < sx1; j++) {
159                         int kv = (ki >> INDEX_FRACTION);
160                         if(kv > kn) break;
161                         if(kv >= -kn) {
162                                 /*
163                                  * the contribution of the first and last input pixel (if
164                                  * fractional) are linearly weighted by the fraction
165                                  */
166                                 float fk = k[abs(kv)];
167                                 wacc += j == i1i ? fk * i1f : j+1 == i2i ? fk * i2f : fk;
168
169                                 /* this is where we clip the kernel convolution to the source plane */
170                                 if(j >= 0 && j < iw) {
171                                         if(lookup_sx0[i] == -1) {
172                                                 lookup_sx0[i] = j;
173                                                 lookup_sk[i] = ki;
174                                         }
175                                         lookup_sx1[i] = j + 1;
176                                 }
177                         }
178                         ki += kd;
179                 }
180                 lookup_wacc[i] = wacc > 0. ? 1. / wacc : 0.;
181         }
182
183         int cols = col_out2 - col_out1;
184         int pkgs = get_total_packages();
185         int col1 = col_out1, col2 = col1;
186         for(int i = 0; i < pkgs; col1=col2 ) {
187                 SamplePackage *package = (SamplePackage*)get_package(i);
188                 col2 = ++i * cols / pkgs + col_out1;
189                 package->out_col1 = col1;
190                 package->out_col2 = col2;
191         }
192 }
193
194 LoadClient* SampleEngine::new_client()
195 {
196         return new SampleUnit(this);
197 }
198
199 LoadPackage* SampleEngine::new_package()
200 {
201         return new SamplePackage;
202 }
203
204