2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU General Public License as published
4 * by the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * General Public License for more details.
12 * You should have received a copy of the GNU General Public
13 * License along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 #include "overlayframe.h"
19 #include "overlaysample.h"
21 /* Fully resampled scale / translate / blend ******************************/
22 /* resample into a temporary row vector, then blend */
24 SamplePackage::SamplePackage()
28 SampleUnit::SampleUnit(SampleEngine *server)
31 this->engine = server;
34 SampleUnit::~SampleUnit()
38 void SampleUnit::process_package(LoadPackage *package)
40 pkg = (SamplePackage*)package;
42 float i1 = engine->in1;
43 float i2 = engine->in2;
44 float o1 = engine->out1;
45 float o2 = engine->out2;
47 if(i2 - i1 <= 0 || o2 - o1 <= 0)
50 voutput = engine->output;
51 vinput = engine->input;
53 fade = BC_CModels::has_alpha(vinput->get_color_model()) &&
54 mode == TRANSFER_REPLACE ? 1.f : engine->alpha;
56 //iw = vinput->get_w();
68 k = engine->kernel->lookup;
69 //kw = engine->kernel->width;
70 //kn = engine->kernel->n;
73 lookup_sx0 = engine->lookup_sx0;
74 lookup_sx1 = engine->lookup_sx1;
75 lookup_sk = engine->lookup_sk;
76 lookup_wacc = engine->lookup_wacc;
78 switch( vinput->get_color_model() ) {
79 case BC_RGB_FLOAT: rgb_float(); break;
80 case BC_RGBA_FLOAT: rgba_float(); break;
81 case BC_RGB888: rgb888(); break;
82 case BC_YUV888: yuv888(); break;
83 case BC_RGBA8888: rgba8888(); break;
84 case BC_YUVA8888: yuva8888(); break;
85 case BC_RGB161616: rgb161616(); break;
86 case BC_YUV161616: yuv161616(); break;
87 case BC_RGBA16161616: rgba16161616(); break;
88 case BC_YUVA16161616: yuva16161616(); break;
93 SampleEngine::SampleEngine(int cpus)
94 : LoadServer(cpus, cpus)
103 SampleEngine::~SampleEngine()
105 if(lookup_sx0) delete [] lookup_sx0;
106 if(lookup_sx1) delete [] lookup_sx1;
107 if(lookup_sk) delete [] lookup_sk;
108 if(lookup_wacc) delete [] lookup_wacc;
112 * unlike the Direct and NN engines, the Sample engine works across
113 * output columns (it makes for more economical memory addressing
114 * during convolution)
116 void SampleEngine::init_packages()
118 int iw = input->get_w();
119 int i1i = floor(in1);
121 float i1f = 1.f - in1 + i1i;
122 float i2f = 1.f - i2i + in2;
124 int oy = floor(out1);
125 float oyf = out1 - oy;
126 int oh = ceil(out2) - oy;
128 float *k = kernel->lookup;
129 float kw = kernel->width;
132 if(in2 - in1 <= 0 || out2 - out1 <= 0)
135 /* determine kernel spatial coverage */
136 float scale = (out2 - out1) / (in2 - in1);
137 float iscale = (in2 - in1) / (out2 - out1);
138 float coverage = fabs(1.f / scale);
139 float bound = (coverage < 1.f ? kw : kw * coverage) - (.5f / TRANSFORM_SPP);
140 float coeff = (coverage < 1.f ? 1.f : scale) * TRANSFORM_SPP;
142 delete [] lookup_sx0;
143 delete [] lookup_sx1;
145 delete [] lookup_wacc;
147 lookup_sx0 = new int[oh];
148 lookup_sx1 = new int[oh];
149 lookup_sk = new int[oh];
150 lookup_wacc = new float[oh];
152 kd = (double)coeff * (1 << INDEX_FRACTION) + .5;
154 /* precompute kernel values and weight sums */
155 for(int i = 0; i < oh; i++) {
156 /* map destination back to source */
157 double sx = (i - oyf + .5) * iscale + in1 - .5;
160 * clip iteration to source area but not source plane. Points
161 * outside the source plane count as transparent. Points outside
162 * the source area don't count at all. The actual convolution
163 * later will be clipped to both, but we need to compute
166 int sx0 = mmax((int)floor(sx - bound) + 1, i1i);
167 int sx1 = mmin((int)ceil(sx + bound), i2i);
168 int ki = (double)(sx0 - sx) * coeff * (1 << INDEX_FRACTION)
169 + (1 << (INDEX_FRACTION - 1)) + .5;
175 for(int j= sx0; j < sx1; j++) {
176 int kv = (ki >> INDEX_FRACTION);
180 * the contribution of the first and last input pixel (if
181 * fractional) are linearly weighted by the fraction
183 float fk = k[abs(kv)];
184 wacc += j == i1i ? fk * i1f : j+1 == i2i ? fk * i2f : fk;
186 /* this is where we clip the kernel convolution to the source plane */
187 if(j >= 0 && j < iw) {
188 if(lookup_sx0[i] == -1) {
192 lookup_sx1[i] = j + 1;
197 lookup_wacc[i] = wacc > 0. ? 1. / wacc : 0.;
200 int cols = col_out2 - col_out1;
201 int pkgs = get_total_packages();
202 int col1 = col_out1, col2 = col1;
203 for(int i = 0; i < pkgs; col1=col2 ) {
204 SamplePackage *package = (SamplePackage*)get_package(i);
205 col2 = ++i * cols / pkgs + col_out1;
206 package->out_col1 = col1;
207 package->out_col2 = col2;
211 LoadClient* SampleEngine::new_client()
213 return new SampleUnit(this);
216 LoadPackage* SampleEngine::new_package()
218 return new SamplePackage;