bff8ac767cf7b88794a1741176570ba2ac97fb93
[platform/upstream/gstreamer.git] / gst / videoscale / vs_image.c
1 /*
2  * Image Scaling Functions
3  * Copyright (c) 2005 David A. Schleef <ds@schleef.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <string.h>
29
30 #include "vs_scanline.h"
31 #include "vs_image.h"
32
33 #include "gstvideoscaleorc.h"
34 #include <gst/gst.h>
35
36 #define ROUND_UP_2(x)  (((x)+1)&~1)
37 #define ROUND_UP_4(x)  (((x)+3)&~3)
38 #define ROUND_UP_8(x)  (((x)+7)&~7)
39
40 void
41 vs_image_scale_nearest_RGBA (const VSImage * dest, const VSImage * src,
42     uint8_t * tmpbuf)
43 {
44   int acc;
45   int y_increment;
46   int x_increment;
47   int i;
48   int j;
49   int prev_j;
50
51   if (dest->height == 1)
52     y_increment = 0;
53   else
54     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
55
56   if (dest->width == 1)
57     x_increment = 0;
58   else
59     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
60
61
62   acc = 0;
63   prev_j = -1;
64   for (i = 0; i < dest->height; i++) {
65     j = acc >> 16;
66
67     if (j == prev_j) {
68       memcpy (dest->pixels + i * dest->stride,
69           dest->pixels + (i - 1) * dest->stride, dest->width * 4);
70     } else {
71       gst_videoscale_orc_resample_nearest_u32 (dest->pixels + i * dest->stride,
72           src->pixels + j * src->stride, 0, x_increment, dest->width);
73     }
74
75     prev_j = j;
76     acc += y_increment;
77   }
78 }
79
80 void
81 vs_image_scale_linear_RGBA (const VSImage * dest, const VSImage * src,
82     uint8_t * tmpbuf)
83 {
84   int acc;
85   int y_increment;
86   int x_increment;
87   int y1;
88   int y2;
89   int i;
90   int j;
91   int x;
92   int dest_size;
93
94   if (dest->height == 1)
95     y_increment = 0;
96   else
97     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
98
99   if (dest->width == 1)
100     x_increment = 0;
101   else
102     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
103
104   dest_size = dest->width * 4;
105
106 #define LINE(x) ((tmpbuf) + (dest_size)*((x)&1))
107
108   acc = 0;
109   y2 = -1;
110   gst_videoscale_orc_resample_bilinear_u32 (LINE (0), src->pixels,
111       0, x_increment, dest->width);
112   y1 = 0;
113   for (i = 0; i < dest->height; i++) {
114     j = acc >> 16;
115     x = acc & 0xffff;
116
117     if (x == 0) {
118       memcpy (dest->pixels + i * dest->stride, LINE (j), dest_size);
119     } else {
120       if (j > y1) {
121         gst_videoscale_orc_resample_bilinear_u32 (LINE (j),
122             src->pixels + j * src->stride, 0, x_increment, dest->width);
123         y1++;
124       }
125       if (j >= y1) {
126         gst_videoscale_orc_resample_merge_bilinear_u32 (dest->pixels +
127             i * dest->stride, LINE (j + 1), LINE (j),
128             src->pixels + (j + 1) * src->stride, (x >> 8), 0, x_increment,
129             dest->width);
130         y1++;
131       } else {
132         orc_merge_linear_u8 (dest->pixels + i * dest->stride,
133             LINE (j), LINE (j + 1), (x >> 8), dest->width * 4);
134       }
135     }
136
137     acc += y_increment;
138   }
139 }
140
141
142 void
143 vs_image_scale_nearest_RGB (const VSImage * dest, const VSImage * src,
144     uint8_t * tmpbuf)
145 {
146   int acc;
147   int y_increment;
148   int x_increment;
149   int i;
150   int j;
151   int xacc;
152
153   if (dest->height == 1)
154     y_increment = 0;
155   else
156     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
157
158   if (dest->width == 1)
159     x_increment = 0;
160   else
161     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
162
163   acc = 0;
164   for (i = 0; i < dest->height; i++) {
165     j = acc >> 16;
166
167     xacc = 0;
168     vs_scanline_resample_nearest_RGB (dest->pixels + i * dest->stride,
169         src->pixels + j * src->stride, src->width, dest->width, &xacc,
170         x_increment);
171
172     acc += y_increment;
173   }
174 }
175
176 void
177 vs_image_scale_linear_RGB (const VSImage * dest, const VSImage * src,
178     uint8_t * tmpbuf)
179 {
180   int acc;
181   int y_increment;
182   int x_increment;
183   uint8_t *tmp1;
184   uint8_t *tmp2;
185   int y1;
186   int y2;
187   int i;
188   int j;
189   int x;
190   int dest_size;
191   int xacc;
192
193   if (dest->height == 1)
194     y_increment = 0;
195   else
196     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
197
198   if (dest->width == 1)
199     x_increment = 0;
200   else
201     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
202
203   dest_size = dest->width * 3;
204
205   tmp1 = tmpbuf;
206   tmp2 = tmpbuf + dest_size;
207
208   acc = 0;
209   xacc = 0;
210   y2 = -1;
211   vs_scanline_resample_linear_RGB (tmp1, src->pixels, src->width, dest->width,
212       &xacc, x_increment);
213   y1 = 0;
214   for (i = 0; i < dest->height; i++) {
215     j = acc >> 16;
216     x = acc & 0xffff;
217
218     if (x == 0) {
219       if (j == y1) {
220         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
221       } else if (j == y2) {
222         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
223       } else {
224         xacc = 0;
225         vs_scanline_resample_linear_RGB (tmp1, src->pixels + j * src->stride,
226             src->width, dest->width, &xacc, x_increment);
227         y1 = j;
228         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
229       }
230     } else {
231       if (j == y1) {
232         if (j + 1 != y2) {
233           xacc = 0;
234           vs_scanline_resample_linear_RGB (tmp2,
235               src->pixels + (j + 1) * src->stride, src->width, dest->width,
236               &xacc, x_increment);
237           y2 = j + 1;
238         }
239         vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride,
240             tmp1, tmp2, dest->width, x);
241       } else if (j == y2) {
242         if (j + 1 != y1) {
243           xacc = 0;
244           vs_scanline_resample_linear_RGB (tmp1,
245               src->pixels + (j + 1) * src->stride, src->width, dest->width,
246               &xacc, x_increment);
247           y1 = j + 1;
248         }
249         vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride,
250             tmp2, tmp1, dest->width, x);
251       } else {
252         xacc = 0;
253         vs_scanline_resample_linear_RGB (tmp1, src->pixels + j * src->stride,
254             src->width, dest->width, &xacc, x_increment);
255         y1 = j;
256         xacc = 0;
257         vs_scanline_resample_linear_RGB (tmp2,
258             src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
259             x_increment);
260         y2 = (j + 1);
261         vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride,
262             tmp1, tmp2, dest->width, x);
263       }
264     }
265
266     acc += y_increment;
267   }
268 }
269
270 /* YUYV */
271
272 void
273 vs_image_scale_nearest_YUYV (const VSImage * dest, const VSImage * src,
274     uint8_t * tmpbuf)
275 {
276   int acc;
277   int y_increment;
278   int x_increment;
279   int i;
280   int j;
281   int xacc;
282
283   if (dest->height == 1)
284     y_increment = 0;
285   else
286     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
287
288   if (dest->width == 1)
289     x_increment = 0;
290   else
291     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
292
293   acc = 0;
294   for (i = 0; i < dest->height; i++) {
295     j = acc >> 16;
296
297     xacc = 0;
298     vs_scanline_resample_nearest_YUYV (dest->pixels + i * dest->stride,
299         src->pixels + j * src->stride, src->width, dest->width, &xacc,
300         x_increment);
301
302     acc += y_increment;
303   }
304 }
305
306 void
307 vs_image_scale_linear_YUYV (const VSImage * dest, const VSImage * src,
308     uint8_t * tmpbuf)
309 {
310   int acc;
311   int y_increment;
312   int x_increment;
313   uint8_t *tmp1;
314   uint8_t *tmp2;
315   int y1;
316   int y2;
317   int i;
318   int j;
319   int x;
320   int dest_size;
321   int xacc;
322
323   if (dest->height == 1)
324     y_increment = 0;
325   else
326     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
327
328   if (dest->width == 1)
329     x_increment = 0;
330   else
331     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
332
333   dest_size = ROUND_UP_4 (dest->width * 2);
334
335   tmp1 = tmpbuf;
336   tmp2 = tmpbuf + dest_size;
337
338   acc = 0;
339   xacc = 0;
340   y2 = -1;
341   vs_scanline_resample_linear_YUYV (tmp1, src->pixels, src->width, dest->width,
342       &xacc, x_increment);
343   y1 = 0;
344   for (i = 0; i < dest->height; i++) {
345     j = acc >> 16;
346     x = acc & 0xffff;
347
348     if (x == 0) {
349       if (j == y1) {
350         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
351       } else if (j == y2) {
352         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
353       } else {
354         xacc = 0;
355         vs_scanline_resample_linear_YUYV (tmp1, src->pixels + j * src->stride,
356             src->width, dest->width, &xacc, x_increment);
357         y1 = j;
358         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
359       }
360     } else {
361       if (j == y1) {
362         if (j + 1 != y2) {
363           xacc = 0;
364           vs_scanline_resample_linear_YUYV (tmp2,
365               src->pixels + (j + 1) * src->stride, src->width, dest->width,
366               &xacc, x_increment);
367           y2 = j + 1;
368         }
369         vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride,
370             tmp1, tmp2, dest->width, x);
371       } else if (j == y2) {
372         if (j + 1 != y1) {
373           xacc = 0;
374           vs_scanline_resample_linear_YUYV (tmp1,
375               src->pixels + (j + 1) * src->stride, src->width, dest->width,
376               &xacc, x_increment);
377           y1 = j + 1;
378         }
379         vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride,
380             tmp2, tmp1, dest->width, x);
381       } else {
382         xacc = 0;
383         vs_scanline_resample_linear_YUYV (tmp1, src->pixels + j * src->stride,
384             src->width, dest->width, &xacc, x_increment);
385         y1 = j;
386         xacc = 0;
387         vs_scanline_resample_linear_YUYV (tmp2,
388             src->pixels + (j + 1) * src->stride, src->width, dest->width,
389             &xacc, x_increment);
390         y2 = (j + 1);
391         vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride,
392             tmp1, tmp2, dest->width, x);
393       }
394     }
395
396     acc += y_increment;
397   }
398 }
399
400 /* UYVY */
401
402 void
403 vs_image_scale_nearest_UYVY (const VSImage * dest, const VSImage * src,
404     uint8_t * tmpbuf)
405 {
406   int acc;
407   int y_increment;
408   int x_increment;
409   int i;
410   int j;
411   int xacc;
412
413   if (dest->height == 1)
414     y_increment = 0;
415   else
416     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
417
418   if (dest->width == 1)
419     x_increment = 0;
420   else
421     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
422
423   acc = 0;
424   for (i = 0; i < dest->height; i++) {
425     j = acc >> 16;
426
427     xacc = 0;
428     vs_scanline_resample_nearest_UYVY (dest->pixels + i * dest->stride,
429         src->pixels + j * src->stride, src->width, dest->width, &xacc,
430         x_increment);
431
432     acc += y_increment;
433   }
434 }
435
436 void
437 vs_image_scale_linear_UYVY (const VSImage * dest, const VSImage * src,
438     uint8_t * tmpbuf)
439 {
440   int acc;
441   int y_increment;
442   int x_increment;
443   uint8_t *tmp1;
444   uint8_t *tmp2;
445   int y1;
446   int y2;
447   int i;
448   int j;
449   int x;
450   int dest_size;
451   int xacc;
452
453   if (dest->height == 1)
454     y_increment = 0;
455   else
456     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
457
458   if (dest->width == 1)
459     x_increment = 0;
460   else
461     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
462
463   dest_size = ROUND_UP_4 (dest->width * 2);
464
465   tmp1 = tmpbuf;
466   tmp2 = tmpbuf + dest_size;
467
468   acc = 0;
469   xacc = 0;
470   y2 = -1;
471   vs_scanline_resample_linear_UYVY (tmp1, src->pixels, src->width, dest->width,
472       &xacc, x_increment);
473   y1 = 0;
474   for (i = 0; i < dest->height; i++) {
475     j = acc >> 16;
476     x = acc & 0xffff;
477
478     if (x == 0) {
479       if (j == y1) {
480         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
481       } else if (j == y2) {
482         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
483       } else {
484         xacc = 0;
485         vs_scanline_resample_linear_UYVY (tmp1, src->pixels + j * src->stride,
486             src->width, dest->width, &xacc, x_increment);
487         y1 = j;
488         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
489       }
490     } else {
491       if (j == y1) {
492         if (j + 1 != y2) {
493           xacc = 0;
494           vs_scanline_resample_linear_UYVY (tmp2,
495               src->pixels + (j + 1) * src->stride, src->width, dest->width,
496               &xacc, x_increment);
497           y2 = j + 1;
498         }
499         vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride,
500             tmp1, tmp2, dest->width, x);
501       } else if (j == y2) {
502         if (j + 1 != y1) {
503           xacc = 0;
504           vs_scanline_resample_linear_UYVY (tmp1,
505               src->pixels + (j + 1) * src->stride, src->width, dest->width,
506               &xacc, x_increment);
507           y1 = j + 1;
508         }
509         vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride,
510             tmp2, tmp1, dest->width, x);
511       } else {
512         xacc = 0;
513         vs_scanline_resample_linear_UYVY (tmp1, src->pixels + j * src->stride,
514             src->width, dest->width, &xacc, x_increment);
515         y1 = j;
516         xacc = 0;
517         vs_scanline_resample_linear_UYVY (tmp2,
518             src->pixels + (j + 1) * src->stride, src->width, dest->width,
519             &xacc, x_increment);
520         y2 = (j + 1);
521         vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride,
522             tmp1, tmp2, dest->width, x);
523       }
524     }
525
526     acc += y_increment;
527   }
528 }
529
530 /* greyscale */
531
532 void
533 vs_image_scale_nearest_Y (const VSImage * dest, const VSImage * src,
534     uint8_t * tmpbuf)
535 {
536   int acc;
537   int y_increment;
538   int x_increment;
539   int i;
540   int j;
541
542   if (dest->height == 1)
543     y_increment = 0;
544   else
545     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
546
547   if (dest->width == 1)
548     x_increment = 0;
549   else
550     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
551
552   acc = 0;
553   for (i = 0; i < dest->height; i++) {
554     j = acc >> 16;
555
556     gst_videoscale_orc_resample_nearest_u8 (dest->pixels + i * dest->stride,
557         src->pixels + j * src->stride, 0, x_increment, dest->width);
558     acc += y_increment;
559   }
560 }
561
562 void
563 vs_image_scale_linear_Y (const VSImage * dest, const VSImage * src,
564     uint8_t * tmpbuf)
565 {
566   int acc;
567   int y_increment;
568   int x_increment;
569   uint8_t *tmp1;
570   uint8_t *tmp2;
571   int y1;
572   int y2;
573   int i;
574   int j;
575   int x;
576   int dest_size;
577   int xacc;
578
579   if (dest->height == 1)
580     y_increment = 0;
581   else
582     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
583
584   if (dest->width == 1)
585     x_increment = 0;
586   else
587     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
588
589   dest_size = dest->width;
590
591   tmp1 = tmpbuf;
592   tmp2 = tmpbuf + dest_size;
593
594   acc = 0;
595   xacc = 0;
596   y2 = -1;
597   gst_videoscale_orc_resample_bilinear_u8 (tmp1, src->pixels,
598       0, x_increment, dest->width);
599   y1 = 0;
600   for (i = 0; i < dest->height; i++) {
601     j = acc >> 16;
602     x = acc & 0xffff;
603
604     if (x == 0) {
605       if (j == y1) {
606         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
607       } else if (j == y2) {
608         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
609       } else {
610         xacc = 0;
611         gst_videoscale_orc_resample_bilinear_u8 (tmp1,
612             src->pixels + j * src->stride, 0, x_increment, dest->width);
613         y1 = j;
614         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
615       }
616     } else {
617       if (j == y1) {
618         if (j + 1 != y2) {
619           xacc = 0;
620           gst_videoscale_orc_resample_bilinear_u8 (tmp2,
621               src->pixels + (j + 1) * src->stride, 0, x_increment, dest->width);
622           y2 = j + 1;
623         }
624         if ((x >> 8) == 0) {
625           memcpy (dest->pixels + i * dest->stride, tmp1, dest->width);
626         } else {
627           orc_merge_linear_u8 (dest->pixels + i * dest->stride,
628               tmp1, tmp2, (x >> 8), dest->width);
629         }
630       } else if (j == y2) {
631         if (j + 1 != y1) {
632           xacc = 0;
633           gst_videoscale_orc_resample_bilinear_u8 (tmp1,
634               src->pixels + (j + 1) * src->stride, 0, x_increment, dest->width);
635           y1 = j + 1;
636         }
637         if ((x >> 8) == 0) {
638           memcpy (dest->pixels + i * dest->stride, tmp2, dest->width);
639         } else {
640           orc_merge_linear_u8 (dest->pixels + i * dest->stride,
641               tmp2, tmp1, (x >> 8), dest->width);
642         }
643       } else {
644         gst_videoscale_orc_resample_bilinear_u8 (tmp1,
645             src->pixels + j * src->stride, 0, x_increment, dest->width);
646         y1 = j;
647         gst_videoscale_orc_resample_bilinear_u8 (tmp2,
648             src->pixels + (j + 1) * src->stride, 0, x_increment, dest->width);
649         y2 = (j + 1);
650         if ((x >> 8) == 0) {
651           memcpy (dest->pixels + i * dest->stride, tmp1, dest->width);
652         } else {
653           orc_merge_linear_u8 (dest->pixels + i * dest->stride,
654               tmp1, tmp2, (x >> 8), dest->width);
655         }
656       }
657     }
658
659     acc += y_increment;
660   }
661 }
662
663 void
664 vs_image_scale_nearest_Y16 (const VSImage * dest, const VSImage * src,
665     uint8_t * tmpbuf)
666 {
667   int acc;
668   int y_increment;
669   int x_increment;
670   int i;
671   int j;
672   int xacc;
673
674   if (dest->height == 1)
675     y_increment = 0;
676   else
677     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
678
679   if (dest->width == 1)
680     x_increment = 0;
681   else
682     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
683
684   acc = 0;
685   for (i = 0; i < dest->height; i++) {
686     j = acc >> 16;
687
688     xacc = 0;
689     vs_scanline_resample_nearest_Y16 (dest->pixels + i * dest->stride,
690         src->pixels + j * src->stride, src->width, dest->width, &xacc,
691         x_increment);
692
693     acc += y_increment;
694   }
695 }
696
697 void
698 vs_image_scale_linear_Y16 (const VSImage * dest, const VSImage * src,
699     uint8_t * tmpbuf)
700 {
701   int acc;
702   int y_increment;
703   int x_increment;
704   uint8_t *tmp1;
705   uint8_t *tmp2;
706   int y1;
707   int y2;
708   int i;
709   int j;
710   int x;
711   int dest_size;
712   int xacc;
713
714   if (dest->height == 1)
715     y_increment = 0;
716   else
717     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
718
719   if (dest->width == 1)
720     x_increment = 0;
721   else
722     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
723
724   dest_size = 2 * dest->width;
725
726   tmp1 = tmpbuf;
727   tmp2 = tmpbuf + dest_size;
728
729   acc = 0;
730   xacc = 0;
731   y2 = -1;
732   vs_scanline_resample_linear_Y16 (tmp1, src->pixels, src->width, dest->width,
733       &xacc, x_increment);
734   y1 = 0;
735   for (i = 0; i < dest->height; i++) {
736     j = acc >> 16;
737     x = acc & 0xffff;
738
739     if (x == 0) {
740       if (j == y1) {
741         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
742       } else if (j == y2) {
743         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
744       } else {
745         xacc = 0;
746         vs_scanline_resample_linear_Y16 (tmp1, src->pixels + j * src->stride,
747             src->width, dest->width, &xacc, x_increment);
748         y1 = j;
749         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
750       }
751     } else {
752       if (j == y1) {
753         if (j + 1 != y2) {
754           xacc = 0;
755           vs_scanline_resample_linear_Y16 (tmp2,
756               src->pixels + (j + 1) * src->stride, src->width, dest->width,
757               &xacc, x_increment);
758           y2 = j + 1;
759         }
760         vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride,
761             tmp1, tmp2, dest->width, x);
762       } else if (j == y2) {
763         if (j + 1 != y1) {
764           xacc = 0;
765           vs_scanline_resample_linear_Y16 (tmp1,
766               src->pixels + (j + 1) * src->stride, src->width, dest->width,
767               &xacc, x_increment);
768           y1 = j + 1;
769         }
770         vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride,
771             tmp2, tmp1, dest->width, x);
772       } else {
773         xacc = 0;
774         vs_scanline_resample_linear_Y16 (tmp1, src->pixels + j * src->stride,
775             src->width, dest->width, &xacc, x_increment);
776         y1 = j;
777         xacc = 0;
778         vs_scanline_resample_linear_Y16 (tmp2,
779             src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
780             x_increment);
781         y2 = (j + 1);
782         vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride,
783             tmp1, tmp2, dest->width, x);
784       }
785     }
786
787     acc += y_increment;
788   }
789 }
790
791 /* RGB565 */
792
793 void
794 vs_image_scale_nearest_RGB565 (const VSImage * dest, const VSImage * src,
795     uint8_t * tmpbuf)
796 {
797   int acc;
798   int y_increment;
799   int x_increment;
800   int i;
801   int j;
802   int xacc;
803
804   if (dest->height == 1)
805     y_increment = 0;
806   else
807     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
808
809   if (dest->width == 1)
810     x_increment = 0;
811   else
812     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
813
814   acc = 0;
815   for (i = 0; i < dest->height; i++) {
816     j = acc >> 16;
817
818     xacc = 0;
819     vs_scanline_resample_nearest_RGB565 (dest->pixels + i * dest->stride,
820         src->pixels + j * src->stride, src->width, dest->width, &xacc,
821         x_increment);
822
823     acc += y_increment;
824   }
825 }
826
827 void
828 vs_image_scale_linear_RGB565 (const VSImage * dest, const VSImage * src,
829     uint8_t * tmpbuf)
830 {
831   int acc;
832   int y_increment;
833   int x_increment;
834   uint8_t *tmp1;
835   uint8_t *tmp2;
836   int y1;
837   int y2;
838   int i;
839   int j;
840   int x;
841   int dest_size;
842   int xacc;
843
844   if (dest->height == 1)
845     y_increment = 0;
846   else
847     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
848
849   if (dest->width == 1)
850     x_increment = 0;
851   else
852     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
853
854   dest_size = dest->width * 2;
855
856   tmp1 = tmpbuf;
857   tmp2 = tmpbuf + dest_size;
858
859   acc = 0;
860   xacc = 0;
861   y2 = -1;
862   vs_scanline_resample_linear_RGB565 (tmp1, src->pixels, src->width,
863       dest->width, &xacc, x_increment);
864   y1 = 0;
865   for (i = 0; i < dest->height; i++) {
866     j = acc >> 16;
867     x = acc & 0xffff;
868
869     if (x == 0) {
870       if (j == y1) {
871         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
872       } else if (j == y2) {
873         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
874       } else {
875         xacc = 0;
876         vs_scanline_resample_linear_RGB565 (tmp1, src->pixels + j * src->stride,
877             src->width, dest->width, &xacc, x_increment);
878         y1 = j;
879         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
880       }
881     } else {
882       if (j == y1) {
883         if (j + 1 != y2) {
884           xacc = 0;
885           vs_scanline_resample_linear_RGB565 (tmp2,
886               src->pixels + (j + 1) * src->stride, src->width, dest->width,
887               &xacc, x_increment);
888           y2 = j + 1;
889         }
890         vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride,
891             tmp1, tmp2, dest->width, x);
892       } else if (j == y2) {
893         if (j + 1 != y1) {
894           xacc = 0;
895           vs_scanline_resample_linear_RGB565 (tmp1,
896               src->pixels + (j + 1) * src->stride, src->width, dest->width,
897               &xacc, x_increment);
898           y1 = j + 1;
899         }
900         vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride,
901             tmp2, tmp1, dest->width, x);
902       } else {
903         xacc = 0;
904         vs_scanline_resample_linear_RGB565 (tmp1, src->pixels + j * src->stride,
905             src->width, dest->width, &xacc, x_increment);
906         y1 = j;
907         xacc = 0;
908         vs_scanline_resample_linear_RGB565 (tmp2,
909             src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
910             x_increment);
911         y2 = (j + 1);
912         vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride,
913             tmp1, tmp2, dest->width, x);
914       }
915     }
916
917     acc += y_increment;
918   }
919 }
920
921 /* RGB555 */
922
923 void
924 vs_image_scale_nearest_RGB555 (const VSImage * dest, const VSImage * src,
925     uint8_t * tmpbuf)
926 {
927   int acc;
928   int y_increment;
929   int x_increment;
930   int i;
931   int j;
932   int xacc;
933
934   if (dest->height == 1)
935     y_increment = 0;
936   else
937     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
938
939   if (dest->width == 1)
940     x_increment = 0;
941   else
942     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
943
944   acc = 0;
945   for (i = 0; i < dest->height; i++) {
946     j = acc >> 16;
947
948     xacc = 0;
949     vs_scanline_resample_nearest_RGB555 (dest->pixels + i * dest->stride,
950         src->pixels + j * src->stride, src->width, dest->width, &xacc,
951         x_increment);
952
953     acc += y_increment;
954   }
955 }
956
957 void
958 vs_image_scale_linear_RGB555 (const VSImage * dest, const VSImage * src,
959     uint8_t * tmpbuf)
960 {
961   int acc;
962   int y_increment;
963   int x_increment;
964   uint8_t *tmp1;
965   uint8_t *tmp2;
966   int y1;
967   int y2;
968   int i;
969   int j;
970   int x;
971   int dest_size;
972   int xacc;
973
974   if (dest->height == 1)
975     y_increment = 0;
976   else
977     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
978
979   if (dest->width == 1)
980     x_increment = 0;
981   else
982     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
983
984   dest_size = dest->width * 2;
985
986   tmp1 = tmpbuf;
987   tmp2 = tmpbuf + dest_size;
988
989   acc = 0;
990   xacc = 0;
991   y2 = -1;
992   vs_scanline_resample_linear_RGB555 (tmp1, src->pixels, src->width,
993       dest->width, &xacc, x_increment);
994   y1 = 0;
995   for (i = 0; i < dest->height; i++) {
996     j = acc >> 16;
997     x = acc & 0xffff;
998
999     if (x == 0) {
1000       if (j == y1) {
1001         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
1002       } else if (j == y2) {
1003         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
1004       } else {
1005         xacc = 0;
1006         vs_scanline_resample_linear_RGB555 (tmp1, src->pixels + j * src->stride,
1007             src->width, dest->width, &xacc, x_increment);
1008         y1 = j;
1009         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
1010       }
1011     } else {
1012       if (j == y1) {
1013         if (j + 1 != y2) {
1014           xacc = 0;
1015           vs_scanline_resample_linear_RGB555 (tmp2,
1016               src->pixels + (j + 1) * src->stride, src->width, dest->width,
1017               &xacc, x_increment);
1018           y2 = j + 1;
1019         }
1020         vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride,
1021             tmp1, tmp2, dest->width, x);
1022       } else if (j == y2) {
1023         if (j + 1 != y1) {
1024           xacc = 0;
1025           vs_scanline_resample_linear_RGB555 (tmp1,
1026               src->pixels + (j + 1) * src->stride, src->width, dest->width,
1027               &xacc, x_increment);
1028           y1 = j + 1;
1029         }
1030         vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride,
1031             tmp2, tmp1, dest->width, x);
1032       } else {
1033         xacc = 0;
1034         vs_scanline_resample_linear_RGB555 (tmp1, src->pixels + j * src->stride,
1035             src->width, dest->width, &xacc, x_increment);
1036         y1 = j;
1037         xacc = 0;
1038         vs_scanline_resample_linear_RGB555 (tmp2,
1039             src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
1040             x_increment);
1041         y2 = (j + 1);
1042         vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride,
1043             tmp1, tmp2, dest->width, x);
1044       }
1045     }
1046
1047     acc += y_increment;
1048   }
1049 }
1050
1051 void
1052 vs_image_scale_nearest_AYUV64 (const VSImage * dest, const VSImage * src,
1053     uint8_t * tmpbuf8)
1054 {
1055   int acc;
1056   int y_increment;
1057   int x_increment;
1058   int i;
1059   int j;
1060   int prev_j;
1061
1062   if (dest->height == 1)
1063     y_increment = 0;
1064   else
1065     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
1066
1067   if (dest->width == 1)
1068     x_increment = 0;
1069   else
1070     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
1071
1072
1073   acc = 0;
1074   prev_j = -1;
1075   for (i = 0; i < dest->height; i++) {
1076     j = acc >> 16;
1077
1078     if (j == prev_j) {
1079       memcpy (dest->pixels + i * dest->stride,
1080           dest->pixels + (i - 1) * dest->stride, dest->width * 8);
1081     } else {
1082       int xacc = 0;
1083       vs_scanline_resample_nearest_AYUV64 (dest->pixels + i * dest->stride,
1084           src->pixels + j * src->stride, src->width, dest->width, &xacc,
1085           x_increment);
1086     }
1087
1088     prev_j = j;
1089     acc += y_increment;
1090   }
1091 }
1092
1093 void
1094 vs_image_scale_linear_AYUV64 (const VSImage * dest, const VSImage * src,
1095     uint8_t * tmpbuf)
1096 {
1097   int acc;
1098   int y_increment;
1099   int x_increment;
1100   int y1;
1101   int y2;
1102   int i;
1103   int j;
1104   int x;
1105   int dest_size;
1106   int xacc;
1107
1108   if (dest->height == 1)
1109     y_increment = 0;
1110   else
1111     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
1112
1113   if (dest->width == 1)
1114     x_increment = 0;
1115   else
1116     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
1117
1118   dest_size = dest->width * 8;
1119
1120 #undef LINE
1121 #define LINE(x) ((guint16 *)((tmpbuf) + (dest_size)*((x)&1)))
1122
1123   acc = 0;
1124   y2 = -1;
1125   //gst_videoscale_orc_resample_bilinear_u64 (LINE (0), src->pixels,
1126   //    0, x_increment, dest->width);
1127   xacc = 0;
1128   vs_scanline_resample_linear_AYUV64 ((guint8 *) LINE (0),
1129       src->pixels, src->width, dest->width, &xacc, x_increment);
1130   y1 = 0;
1131   for (i = 0; i < dest->height; i++) {
1132     j = acc >> 16;
1133     x = acc & 0xffff;
1134
1135     if (x == 0) {
1136       memcpy (dest->pixels + i * dest->stride, LINE (j), dest_size);
1137     } else {
1138       if (j > y1) {
1139         xacc = 0;
1140         vs_scanline_resample_linear_AYUV64 ((guint8 *) LINE (j),
1141             src->pixels + j * src->stride, src->width, dest->width, &xacc,
1142             x_increment);
1143         //gst_videoscale_orc_resample_bilinear_u64 (LINE (j),
1144         //    src->pixels + j * src->stride, 0, x_increment, dest->width);
1145         y1++;
1146       }
1147       if (j >= y1) {
1148         xacc = 0;
1149         vs_scanline_resample_linear_AYUV64 ((guint8 *) LINE (j + 1),
1150             src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
1151             x_increment);
1152         orc_merge_linear_u16 ((guint16 *) (dest->pixels + i * dest->stride),
1153             LINE (j), LINE (j + 1), 65536 - x, x, dest->width * 4);
1154         //gst_videoscale_orc_resample_merge_bilinear_u64 (dest->pixels +
1155         //    i * dest->stride, LINE (j + 1), LINE (j),
1156         //    src->pixels + (j + 1) * src->stride, (x >> 8), 0, x_increment,
1157         //    dest->width);
1158         y1++;
1159       } else {
1160         orc_merge_linear_u16 ((guint16 *) (dest->pixels + i * dest->stride),
1161             LINE (j), LINE (j + 1), 65536 - x, x, dest->width * 4);
1162       }
1163     }
1164
1165     acc += y_increment;
1166   }
1167 }