1 /*
2 * transformfixedpoint.c
3 *
4 * Fixed point implementation of image transformations (see also transformfloat.c/h)
5 *
6 * Copyright (C) Georg Martius - June 2011
7 * georg dot martius at web dot de
8 *
9 * This file is part of vid.stab video stabilization library
10 *
11 * vid.stab is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License,
13 * as published by the Free Software Foundation; either version 2, or
14 * (at your option) any later version.
15 *
16 * vid.stab is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with GNU Make; see the file COPYING. If not, write to
23 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 *
26 */
27 #include "transformfixedpoint.h"
28 #include "transform.h"
29 #include "transformtype_operations.h"
30
31 // the orc code does not work at the moment (BUG in ORC?)
32 // #include "orc/transformorc.h"
33
34 //#include <math.h>
35 //#include <libgen.h>
36
37 #define iToFp8(v) ((v)<<8)
38 #define fToFp8(v) ((int32_t)((v)*((float)0xFF)))
39 #define iToFp16(v) ((v)<<16)
40 #define fToFp16(v) ((int32_t)((v)*((double)0xFFFF)))
41 #define fp16To8(v) ((v)>>8)
42 //#define fp16To8(v) ( (v) && 0x80 == 1 ? ((v)>>8 + 1) : ((v)>>8) )
43 #define fp24To8(v) ((v)>>16)
44
45 #define fp8ToI(v) ((v)>>8)
46 #define fp16ToI(v) ((v)>>16)
47 #define fp8ToF(v) ((v)/((double)(1<<8)))
48 #define fp16ToF(v) ((v)/((double)(1<<16)))
49
50 // #define fp8ToIRound(v) ( (((v)>>7) & 0x1) == 0 ? ((v)>>8) : ((v)>>8)+1 )
51 #define fp8_0_5 (1<<7)
52 #define fp8ToIRound(v) (((v) + fp8_0_5) >> 7)
53 //#define fp16ToIRound(v) ( (((v)>>15) & 0x1) == 0 ? ((v)>>16) : ((v)>>16)+1 )
54 #define fp16_0_5 (1<<15)
55 #define fp16ToIRound(v) (((v) + fp16_0_5) >> 16)
56
57 /** interpolateBiLinBorder: bi-linear interpolation function that also works at the border.
58 This is used by many other interpolation methods at and outsize the border, see interpolate */
interpolateBiLinBorder(uint8_t * rv,fp16 x,fp16 y,const uint8_t * img,int img_linesize,int32_t width,int32_t height,uint8_t def)59 inline void interpolateBiLinBorder(uint8_t *rv, fp16 x, fp16 y,
60 const uint8_t *img, int img_linesize,
61 int32_t width, int32_t height, uint8_t def)
62 {
63 int32_t ix_f = fp16ToI(x);
64 int32_t iy_f = fp16ToI(y);
65 int32_t ix_c = ix_f + 1;
66 int32_t iy_c = iy_f + 1;
67 if (ix_f < 0 || ix_c >= width || iy_f < 0 || iy_c >= height) {
68 int32_t w = 10; // number of pixels to blur out the border pixel outwards
69 int32_t xl = - w - ix_f;
70 int32_t yl = - w - iy_f;
71 int32_t xh = ix_c - w - width;
72 int32_t yh = iy_c - w - height;
73 int32_t c = VS_MAX(VS_MIN(VS_MAX(xl, VS_MAX(yl, VS_MAX(xh, yh))),w),0);
74 // pixel at border of source image
75 short val_border = PIX(img, img_linesize, VS_MAX(VS_MIN(ix_f, width-1),0),
76 VS_MAX(VS_MIN(iy_f, height-1),0));
77 *rv = (def * c + val_border * (w - c)) / w;
78 }else{
79 short v1 = PIXEL(img, img_linesize, ix_c, iy_c, width, height, def);
80 short v2 = PIXEL(img, img_linesize, ix_c, iy_f, width, height, def);
81 short v3 = PIXEL(img, img_linesize, ix_f, iy_c, width, height, def);
82 short v4 = PIXEL(img, img_linesize, ix_f, iy_f, width, height, def);
83 fp16 x_f = iToFp16(ix_f);
84 fp16 x_c = iToFp16(ix_c);
85 fp16 y_f = iToFp16(iy_f);
86 fp16 y_c = iToFp16(iy_c);
87 fp16 s = fp16To8(v1*(x - x_f)+v3*(x_c - x))*fp16To8(y - y_f) +
88 fp16To8(v2*(x - x_f) + v4*(x_c - x))*fp16To8(y_c - y) + 1;
89 *rv = fp16ToIRound(s);
90 }
91 }
92
93 /** taken from http://en.wikipedia.org/wiki/Bicubic_interpolation for alpha=-0.5
94 in matrix notation:
95 a0-a3 are the neigthboring points where the target point is between a1 and a2
96 t is the point of interpolation (position between a1 and a2) value between 0 and 1
97 | 0, 2, 0, 0 | |a0|
98 |-1, 0, 1, 0 | |a1|
99 (1,t,t^2,t^3) | 2,-5, 4,-1 | |a2|
100 |-1, 3,-3, 1 | |a3|
101 */
102 /* inline static short bicub_kernel(fp16 t, short a0, short a1, short a2, short a3){ */
103 /* // (2*a1 + t*((-a0+a2) + t*((2*a0-5*a1+4*a2-a3) + t*(-a0+3*a1-3*a2+a3) )) ) / 2; */
104 /* return ((iToFp16(2*a1) + t*(-a0+a2 */
105 /* + fp16ToI(t*((2*a0-5*a1+4*a2-a3) */
106 /* + fp16ToI(t*(-a0+3*a1-3*a2+a3)) )) ) */
107 /* ) ) >> 17; */
108 /* } */
109
bicub_kernel(fp16 t,short a0,short a1,short a2,short a3)110 inline static short bicub_kernel(fp16 t, short a0, short a1, short a2, short a3){
111 // (2*a1 + t*((-a0+a2) + t*((2*a0-5*a1+4*a2-a3) + t*(-a0+3*a1-3*a2+a3) )) ) / 2;
112 // we add 1/2 because of truncation errors
113 return fp16ToIRound((iToFp16(2*a1) + t*(-a0+a2
114 + fp16ToIRound(t*((2*a0-5*a1+4*a2-a3)
115 + fp16ToIRound(t*(-a0+3*a1-3*a2+a3)) )) )
116 ) >> 1);
117 }
118
119 /** interpolateBiCub: bi-cubic interpolation function using 4x4 pixel, see interpolate */
interpolateBiCub(uint8_t * rv,fp16 x,fp16 y,const uint8_t * img,int img_linesize,int width,int height,uint8_t def)120 inline void interpolateBiCub(uint8_t *rv, fp16 x, fp16 y,
121 const uint8_t *img, int img_linesize,
122 int width, int height, uint8_t def)
123 {
124 // do a simple linear interpolation at the border
125 int32_t ix_f = fp16ToI(x);
126 int32_t iy_f = fp16ToI(y);
127 if (unlikely(ix_f < 1 || ix_f > width - 3 || iy_f < 1 || iy_f > height - 3)) {
128 interpolateBiLinBorder(rv, x, y, img, img_linesize, width, height, def);
129 } else {
130 fp16 x_f = iToFp16(ix_f);
131 fp16 y_f = iToFp16(iy_f);
132 fp16 tx = x-x_f;
133 short v1 = bicub_kernel(tx,
134 PIX(img, img_linesize, ix_f-1, iy_f-1),
135 PIX(img, img_linesize, ix_f, iy_f-1),
136 PIX(img, img_linesize, ix_f+1, iy_f-1),
137 PIX(img, img_linesize, ix_f+2, iy_f-1));
138 short v2 = bicub_kernel(tx,
139 PIX(img, img_linesize, ix_f-1, iy_f),
140 PIX(img, img_linesize, ix_f, iy_f),
141 PIX(img, img_linesize, ix_f+1, iy_f),
142 PIX(img, img_linesize, ix_f+2, iy_f));
143 short v3 = bicub_kernel(tx,
144 PIX(img, img_linesize, ix_f-1, iy_f+1),
145 PIX(img, img_linesize, ix_f, iy_f+1),
146 PIX(img, img_linesize, ix_f+1, iy_f+1),
147 PIX(img, img_linesize, ix_f+2, iy_f+1));
148 short v4 = bicub_kernel(tx,
149 PIX(img, img_linesize, ix_f-1, iy_f+2),
150 PIX(img, img_linesize, ix_f, iy_f+2),
151 PIX(img, img_linesize, ix_f+1, iy_f+2),
152 PIX(img, img_linesize, ix_f+2, iy_f+2));
153 short res = bicub_kernel(y-y_f, v1, v2, v3, v4);
154 *rv = res < 255 ? res : 255;
155 }
156 }
157
158
159 /** interpolateBiLin: bi-linear interpolation function, see interpolate */
interpolateBiLin(uint8_t * rv,fp16 x,fp16 y,const uint8_t * img,int img_linesize,int32_t width,int32_t height,uint8_t def)160 inline void interpolateBiLin(uint8_t *rv, fp16 x, fp16 y,
161 const uint8_t *img, int img_linesize,
162 int32_t width, int32_t height, uint8_t def)
163 {
164 int32_t ix_f = fp16ToI(x);
165 int32_t iy_f = fp16ToI(y);
166 if (unlikely(ix_f < 0 || ix_f > width - 2 || iy_f < 0 || iy_f > height - 2)) {
167 interpolateBiLinBorder(rv, x, y, img, img_linesize, width, height, def);
168 } else {
169 int32_t ix_c = ix_f + 1;
170 int32_t iy_c = iy_f + 1;
171 short v1 = PIX(img, img_linesize, ix_c, iy_c);
172 short v2 = PIX(img, img_linesize, ix_c, iy_f);
173 short v3 = PIX(img, img_linesize, ix_f, iy_c);
174 short v4 = PIX(img, img_linesize, ix_f, iy_f);
175 fp16 x_f = iToFp16(ix_f);
176 fp16 x_c = iToFp16(ix_c);
177 fp16 y_f = iToFp16(iy_f);
178 fp16 y_c = iToFp16(iy_c);
179 fp16 s = fp16To8(v1*(x - x_f) + v3*(x_c - x))*fp16To8(y - y_f) +
180 fp16To8(v2*(x - x_f) + v4*(x_c - x))*fp16To8(y_c - y);
181 // it is underestimated due to truncation, so we add one
182 short res = fp16ToI(s);
183 *rv = res < 255 ? res+1 : 255;
184 }
185 }
186
187 /** interpolateLin: linear (only x) interpolation function, see interpolate */
interpolateLin(uint8_t * rv,fp16 x,fp16 y,const uint8_t * img,int img_linesize,int width,int height,uint8_t def)188 inline void interpolateLin(uint8_t *rv, fp16 x, fp16 y,
189 const uint8_t *img, int img_linesize,
190 int width, int height, uint8_t def)
191 {
192 int32_t ix_f = fp16ToI(x);
193 int32_t ix_c = ix_f + 1;
194 fp16 x_c = iToFp16(ix_c);
195 fp16 x_f = iToFp16(ix_f);
196 int y_n = fp16ToIRound(y);
197
198 short v1 = PIXEL(img, img_linesize, ix_c, y_n, width, height, def);
199 short v2 = PIXEL(img, img_linesize, ix_f, y_n, width, height, def);
200 fp16 s = v1*(x - x_f) + v2*(x_c - x);
201 short res = fp16ToI(s);
202 *rv = res < 255 ? res : 255;
203 }
204
205 /** interpolateZero: nearest neighbor interpolation function, see interpolate */
interpolateZero(uint8_t * rv,fp16 x,fp16 y,const uint8_t * img,int img_linesize,int width,int height,uint8_t def)206 inline void interpolateZero(uint8_t *rv, fp16 x, fp16 y,
207 const uint8_t *img, int img_linesize,
208 int width, int height, uint8_t def)
209 {
210 int32_t ix_n = fp16ToIRound(x);
211 int32_t iy_n = fp16ToIRound(y);
212 *rv = (uint8_t) PIXEL(img, img_linesize, ix_n, iy_n, width, height, def);
213 }
214
215
216 /**
217 * interpolateN: Bi-linear interpolation function for N channel image.
218 *
219 * Parameters:
220 * rv: destination pixel (call by reference)
221 * x,y: the source coordinates in the image img. Note this
222 * are real-value coordinates, that's why we interpolate
223 * img: source image
224 * width,height: dimension of image
225 * N: number of channels
226 * channel: channel number (0..N-1)
227 * def: default value if coordinates are out of range
228 * Return value: None
229 */
interpolateN(uint8_t * rv,fp16 x,fp16 y,const uint8_t * img,int img_linesize,int width,int height,uint8_t N,uint8_t channel,uint8_t def)230 inline void interpolateN(uint8_t *rv, fp16 x, fp16 y,
231 const uint8_t *img, int img_linesize,
232 int width, int height,
233 uint8_t N, uint8_t channel,
234 uint8_t def)
235 {
236 int32_t ix_f = fp16ToI(x);
237 int32_t iy_f = fp16ToI(y);
238 if (ix_f < 0 || ix_f > width-1 || iy_f < 0 || iy_f > height - 1) {
239 *rv = def;
240 } else {
241 int32_t ix_c = ix_f + 1;
242 int32_t iy_c = iy_f + 1;
243 short v1 = PIXN(img, img_linesize, ix_c, iy_c, N, channel);
244 short v2 = PIXN(img, img_linesize, ix_c, iy_f, N, channel);
245 short v3 = PIXN(img, img_linesize, ix_f, iy_c, N, channel);
246 short v4 = PIXN(img, img_linesize, ix_f, iy_f, N, channel);
247 fp16 x_f = iToFp16(ix_f);
248 fp16 x_c = iToFp16(ix_c);
249 fp16 y_f = iToFp16(iy_f);
250 fp16 y_c = iToFp16(iy_c);
251 fp16 s = fp16To8(v1*(x - x_f)+v3*(x_c - x))*fp16To8(y - y_f) +
252 fp16To8(v2*(x - x_f) + v4*(x_c - x))*fp16To8(y_c - y);
253 *rv = fp16ToIRound(s);
254 }
255 }
256
257
258 /**
259 * transformPacked: applies current transformation to frame
260 * Parameters:
261 * td: private data structure of this filter
262 * Return value:
263 * 0 for failture, 1 for success
264 * Preconditions:
265 * The frame must be in Packed format
266 */
transformPacked(VSTransformData * td,VSTransform t)267 int transformPacked(VSTransformData* td, VSTransform t)
268 {
269 int x = 0, y = 0, k = 0;
270 uint8_t *D_1, *D_2;
271
272 D_1 = td->src.data[0];
273 D_2 = td->destbuf.data[0];
274 fp16 c_s_x = iToFp16(td->fiSrc.width/2);
275 fp16 c_s_y = iToFp16(td->fiSrc.height/2);
276 int32_t c_d_x = td->fiDest.width/2;
277 int32_t c_d_y = td->fiDest.height/2;
278
279 /* for each pixel in the destination image we calc the source
280 * coordinate and make an interpolation:
281 * p_d = c_d + M(p_s - c_s) + t
282 * where p are the points, c the center coordinate,
283 * _s source and _d destination,
284 * t the translation, and M the rotation matrix
285 * p_s = M^{-1}(p_d - c_d - t) + c_s
286 */
287 float z = 1.0-t.zoom/100.0;
288 fp16 zcos_a = fToFp16(z*cos(-t.alpha)); // scaled cos
289 fp16 zsin_a = fToFp16(z*sin(-t.alpha)); // scaled sin
290 fp16 c_tx = c_s_x - fToFp16(t.x);
291 fp16 c_ty = c_s_y - fToFp16(t.y);
292 int channels = td->fiSrc.bytesPerPixel;
293 /* All channels */
294 for (y = 0; y < td->fiDest.height; y++) {
295 int32_t y_d1 = (y - c_d_y);
296 for (x = 0; x < td->fiDest.width; x++) {
297 int32_t x_d1 = (x - c_d_x);
298 fp16 x_s = zcos_a * x_d1 + zsin_a * y_d1 + c_tx;
299 fp16 y_s = -zsin_a * x_d1 + zcos_a * y_d1 + c_ty;
300
301 for (k = 0; k < channels; k++) { // iterate over colors
302 uint8_t *dest = &D_2[x + y * td->destbuf.linesize[0]+k];
303 interpolateN(dest, x_s, y_s, D_1, td->src.linesize[0],
304 td->fiSrc.width, td->fiSrc.height,
305 channels, k, td->conf.crop ? 16 : *dest);
306 }
307 }
308 }
309 return VS_OK;
310 }
311
312 /**
313 * transformPlanar: applies current transformation to frame
314 *
315 * Parameters:
316 * td: private data structure of this filter
317 * Return value:
318 * 0 for failture, 1 for success
319 * Preconditions:
320 * The frame must be in Planar format
321 *
322 * Fixed-point format 32 bit integer:
323 * for image coords we use val<<8
324 * for angle and zoom we use val<<16
325 *
326 */
transformPlanar(VSTransformData * td,VSTransform t)327 int transformPlanar(VSTransformData* td, VSTransform t)
328 {
329 int32_t x = 0, y = 0;
330 uint8_t *dat_1, *dat_2;
331
332 if (t.alpha==0 && t.x==0 && t.y==0 && t.zoom == 0){
333 if(vsFramesEqual(&td->src,&td->destbuf))
334 return VS_OK; // noop
335 else {
336 vsFrameCopy(&td->destbuf, &td->src, &td->fiSrc);
337 return VS_OK;
338 }
339 }
340
341 int plane;
342 for(plane=0; plane< td->fiSrc.planes; plane++){
343 dat_1 = td->src.data[plane];
344 dat_2 = td->destbuf.data[plane];
345 int wsub = vsGetPlaneWidthSubS(&td->fiSrc,plane);
346 int hsub = vsGetPlaneHeightSubS(&td->fiSrc,plane);
347 int dw = CHROMA_SIZE(td->fiDest.width , wsub);
348 int dh = CHROMA_SIZE(td->fiDest.height, hsub);
349 int sw = CHROMA_SIZE(td->fiSrc.width , wsub);
350 int sh = CHROMA_SIZE(td->fiSrc.height , hsub);
351 uint8_t black = plane==0 ? 0 : 0x80;
352
353 fp16 c_s_x = iToFp16(sw / 2);
354 fp16 c_s_y = iToFp16(sh / 2);
355 int32_t c_d_x = dw / 2;
356 int32_t c_d_y = dh / 2;
357
358 float z = 1.0-t.zoom/100.0;
359 fp16 zcos_a = fToFp16(z*cos(-t.alpha)); // scaled cos
360 fp16 zsin_a = fToFp16(z*sin(-t.alpha)); // scaled sin
361 fp16 c_tx = c_s_x - (fToFp16(t.x) >> wsub);
362 fp16 c_ty = c_s_y - (fToFp16(t.y) >> hsub);
363
364 /* for each pixel in the destination image we calc the source
365 * coordinate and make an interpolation:
366 * p_d = c_d + M(p_s - c_s) + t
367 * where p are the points, c the center coordinate,
368 * _s source and _d destination,
369 * t the translation, and M the rotation and scaling matrix
370 * p_s = M^{-1}(p_d - c_d - t) + c_s
371 */
372 for (y = 0; y < dh; y++) {
373 // swapping of the loops brought 15% performace gain
374 int32_t y_d1 = (y - c_d_y);
375 for (x = 0; x < dw; x++) {
376 int32_t x_d1 = (x - c_d_x);
377 fp16 x_s = zcos_a * x_d1 + zsin_a * y_d1 + c_tx;
378 fp16 y_s = -zsin_a * x_d1 + zcos_a * y_d1 + c_ty;
379 uint8_t *dest = &dat_2[x + y * td->destbuf.linesize[plane]];
380 // inlining the interpolation function would bring 10%
381 // (but then we cannot use the function pointer anymore...)
382 td->interpolate(dest, x_s, y_s, dat_1,
383 td->src.linesize[plane], sw, sh,
384 td->conf.crop ? black : *dest);
385 }
386 }
387 }
388
389 return VS_OK;
390 }
391
392
393
394 /* /\** TESTING */
395 /* * transformPlanar_orc: applies current transformation to frame */
396 /* * */
397 /* * Parameters: */
398 /* * td: private data structure of this filter */
399 /* * Return value: */
400 /* * 0 for failture, 1 for success */
401 /* * Preconditions: */
402 /* * The frame must be in Planar format */
403 /* * */
404 /* * Fixed-point format 32 bit integer: */
405 /* * for image coords we use val<<8 */
406 /* * for angle and zoom we use val<<16 */
407 /* * */
408 /* *\/ */
409 /* int transformPlanar_orc(VSTransformData* td, VSTransform t) */
410 /* { */
411 /* int32_t x = 0, y = 0; */
412 /* uint8_t *Y_1, *Y_2, *Cb_1, *Cb_2, *Cr_1, *Cr_2; */
413
414 /* if (t.alpha==0 && t.x==0 && t.y==0 && t.zoom == 0) return VS_OK; // noop */
415
416 /* Y_1 = td->src; */
417 /* Y_2 = td->destbuf; */
418 /* Cb_1 = td->src + td->fiSrc.width * td->fiSrc.height; */
419 /* Cb_2 = td->destbuf + td->fiDest.width * td->fiDest.height; */
420 /* Cr_1 = td->src + 5*td->fiSrc.width * td->fiSrc.height/4; */
421 /* Cr_2 = td->destbuf + 5*td->fiDest.width * td->fiDest.height/4; */
422 /* fp16 c_s_x = iToFp16(td->fiSrc.width / 2); */
423 /* fp16 c_s_y = iToFp16(td->fiSrc.height / 2); */
424 /* int32_t c_d_x = td->fiDest.width / 2; */
425 /* int32_t c_d_y = td->fiDest.height / 2; */
426
427 /* float z = 1.0-t.zoom/100.0; */
428 /* fp16 zcos_a = fToFp16(z*cos(-t.alpha)); // scaled cos */
429 /* fp16 zsin_a = fToFp16(z*sin(-t.alpha)); // scaled sin */
430 /* fp16 c_tx = c_s_x - fToFp16(t.x); */
431 /* fp16 c_ty = c_s_y - fToFp16(t.y); */
432
433 /* /\* for each pixel in the destination image we calc the source */
434 /* * coordinate and make an interpolation: */
435 /* * p_d = c_d + M(p_s - c_s) + t */
436 /* * where p are the points, c the center coordinate, */
437 /* * _s source and _d destination, */
438 /* * t the translation, and M the rotation and scaling matrix */
439 /* * p_s = M^{-1}(p_d - c_d - t) + c_s */
440 /* *\/ */
441 /* /\* Luminance channel *\/ */
442 /* fp16* x_ss = (fp16*)malloc(sizeof(fp16)*td->fiDest.width); */
443 /* fp16* y_ss = (fp16*)malloc(sizeof(fp16)*td->fiDest.width); */
444 /* int32_t* xs = (int32_t*)malloc(sizeof(int32_t)*td->fiDest.width); */
445 /* for (x = 0; x < td->fiDest.width; x++) { // this can go to td */
446 /* xs[x]=x; */
447 /* } */
448
449 /* for (y = 0; y < td->fiDest.height; y++) { */
450 /* int32_t y_d1 = (y - c_d_y); */
451 /* fp16 sin_y = zsin_a * y_d1; */
452 /* fp16 cos_y = zcos_a * y_d1; */
453 /* for (x = 0; x < td->fiDest.width; x++) { */
454 /* int32_t x_d1 = (xs[x] - c_d_x); */
455 /* //x_ss[x] = zcos_a * x_d1 + zsin_a * y_d1 + c_tx; */
456 /* y_ss[x] = -zsin_a * x_d1 + zcos_a * y_d1 + c_ty; */
457 /* } */
458 /* transform_one_line_optimized1 (x_ss, y_ss, xs, y_d1, c_d_x, */
459 /* c_tx, c_ty, zcos_a, zsin_a, sin_y, cos_y, */
460 /* td->fiDest.width); */
461 /* // transform_one_line_optimized (x_ss, y_ss, xs, y_d1, c_d_x, */
462 /* // c_tx, c_ty, zcos_a, zsin_a, td->fiDest.width); */
463
464 /* for (x = 0; x < td->fiDest.width; x++) { */
465 /* uint8_t *dest = &Y_2[x + y * td->fiDest.width]; */
466 /* td->interpolate(dest, x_ss[x], y_ss[x], Y_1, */
467 /* td->fiSrc.width, td->fiSrc.height, */
468 /* td->crop ? 16 : *dest); */
469 /* } */
470 /* } */
471
472 /* /\* Color channels *\/ */
473 /* int32_t ws2 = td->fiSrc.width/2; */
474 /* int32_t wd2 = td->fiDest.width/2; */
475 /* int32_t hs2 = td->fiSrc.height/2; */
476 /* int32_t hd2 = td->fiDest.height/2; */
477 /* fp16 c_tx2 = c_tx/2; */
478 /* fp16 c_ty2 = c_ty/2; */
479
480 /* for (y = 0; y < hd2; y++) { */
481 /* int32_t y_d1 = y - (c_d_y)/2; */
482 /* for (x = 0; x < wd2; x++) { */
483 /* int32_t x_d1 = x - (c_d_x)/2; */
484 /* fp16 x_s = zcos_a * x_d1 + zsin_a * y_d1 + c_tx2; */
485 /* fp16 y_s = -zsin_a * x_d1 + zcos_a * y_d1 + c_ty2; */
486 /* uint8_t *dest = &Cr_2[x + y * wd2]; */
487 /* td->interpolate(dest, x_s, y_s, Cr_1, ws2, hs2, */
488 /* td->crop ? 128 : *dest); */
489 /* dest = &Cb_2[x + y * wd2]; */
490 /* td->interpolate(dest, x_s, y_s, Cb_1, ws2, hs2, */
491 /* td->crop ? 128 : *dest); */
492 /* } */
493 /* } */
494
495 /* return VS_OK; */
496 /* } */
497
498 /*
499 some debugging stuff
500 FILE* f1 = fopen("transFP.pos","w");
501 fprintf(f1,"%i,%i:\t %f,%f\n", x, y, x_s / (float)(1<<16), y_s / (float)(1<<16));
502 fclose(f1);
503
504 */
505
506
507
508 /*
509 * Local variables:
510 * c-file-style: "stroustrup"
511 * c-file-offsets: ((case-label . *) (statement-case-intro . *))
512 * indent-tabs-mode: nil
513 * c-basic-offset: 2 t
514 *
515 * End:
516 *
517 * vim: expandtab shiftwidth=2:
518 */
519