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