1 #include "overlayframe.h"
2 #include "overlaysample.h"
4 /* Fully resampled scale / translate / blend ******************************/
5 /* resample into a temporary row vector, then blend */
7 SamplePackage::SamplePackage()
11 SampleUnit::SampleUnit(SampleEngine *server)
14 this->engine = server;
17 SampleUnit::~SampleUnit()
21 void SampleUnit::process_package(LoadPackage *package)
23 pkg = (SamplePackage*)package;
25 float i1 = engine->in1;
26 float i2 = engine->in2;
27 float o1 = engine->out1;
28 float o2 = engine->out2;
30 if(i2 - i1 <= 0 || o2 - o1 <= 0)
33 voutput = engine->output;
34 vinput = engine->input;
36 fade = BC_CModels::has_alpha(vinput->get_color_model()) &&
37 mode == TRANSFER_REPLACE ? 1.f : engine->alpha;
39 //iw = vinput->get_w();
51 k = engine->kernel->lookup;
52 //kw = engine->kernel->width;
53 //kn = engine->kernel->n;
56 lookup_sx0 = engine->lookup_sx0;
57 lookup_sx1 = engine->lookup_sx1;
58 lookup_sk = engine->lookup_sk;
59 lookup_wacc = engine->lookup_wacc;
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;
76 SampleEngine::SampleEngine(int cpus)
77 : LoadServer(cpus, cpus)
86 SampleEngine::~SampleEngine()
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;
95 * unlike the Direct and NN engines, the Sample engine works across
96 * output columns (it makes for more economical memory addressing
99 void SampleEngine::init_packages()
101 int iw = input->get_w();
102 int i1i = floor(in1);
104 float i1f = 1.f - in1 + i1i;
105 float i2f = 1.f - i2i + in2;
107 int oy = floor(out1);
108 float oyf = out1 - oy;
109 int oh = ceil(out2) - oy;
111 float *k = kernel->lookup;
112 float kw = kernel->width;
115 if(in2 - in1 <= 0 || out2 - out1 <= 0)
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;
125 delete [] lookup_sx0;
126 delete [] lookup_sx1;
128 delete [] lookup_wacc;
130 lookup_sx0 = new int[oh];
131 lookup_sx1 = new int[oh];
132 lookup_sk = new int[oh];
133 lookup_wacc = new float[oh];
135 kd = (double)coeff * (1 << INDEX_FRACTION) + .5;
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;
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
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;
158 for(int j= sx0; j < sx1; j++) {
159 int kv = (ki >> INDEX_FRACTION);
163 * the contribution of the first and last input pixel (if
164 * fractional) are linearly weighted by the fraction
166 float fk = k[abs(kv)];
167 wacc += j == i1i ? fk * i1f : j+1 == i2i ? fk * i2f : fk;
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) {
175 lookup_sx1[i] = j + 1;
180 lookup_wacc[i] = wacc > 0. ? 1. / wacc : 0.;
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;
194 LoadClient* SampleEngine::new_client()
196 return new SampleUnit(this);
199 LoadPackage* SampleEngine::new_package()
201 return new SamplePackage;