typefinding: detect stand-alone SSA/ASS subtitle files
[platform/upstream/gstreamer.git] / gst / videoscale / vs_image.c
1 /*
2  * Image Scaling Functions
3  * Copyright (c) 2005-2012 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       video_scale_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 i;
89   int j;
90   int x;
91   int dest_size;
92
93   if (dest->height == 1)
94     y_increment = 0;
95   else
96     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
97
98   if (dest->width == 1)
99     x_increment = 0;
100   else
101     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
102
103   dest_size = dest->width * 4;
104
105 #define LINE(x) ((tmpbuf) + (dest_size)*((x)&1))
106
107   acc = 0;
108   video_scale_orc_resample_bilinear_u32 (LINE (0), src->pixels,
109       0, x_increment, dest->width);
110   y1 = 0;
111   for (i = 0; i < dest->height; i++) {
112     j = acc >> 16;
113     x = acc & 0xffff;
114
115     if (x == 0) {
116       memcpy (dest->pixels + i * dest->stride, LINE (j), dest_size);
117     } else {
118       if (j > y1) {
119         video_scale_orc_resample_bilinear_u32 (LINE (j),
120             src->pixels + j * src->stride, 0, x_increment, dest->width);
121         y1++;
122       }
123       if (j >= y1) {
124         video_scale_orc_resample_bilinear_u32 (LINE (j + 1),
125             src->pixels + (j + 1) * src->stride, 0, x_increment, dest->width);
126         y1++;
127       }
128       video_scale_orc_merge_linear_u8 (dest->pixels + i * dest->stride,
129           LINE (j), LINE (j + 1), (x >> 8), dest->width * 4);
130     }
131
132     acc += y_increment;
133   }
134 }
135
136
137 void
138 vs_image_scale_nearest_RGB (const VSImage * dest, const VSImage * src,
139     uint8_t * tmpbuf)
140 {
141   int acc;
142   int y_increment;
143   int x_increment;
144   int i;
145   int j;
146   int xacc;
147
148   if (dest->height == 1)
149     y_increment = 0;
150   else
151     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
152
153   if (dest->width == 1)
154     x_increment = 0;
155   else
156     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
157
158   acc = 0;
159   for (i = 0; i < dest->height; i++) {
160     j = acc >> 16;
161
162     xacc = 0;
163     vs_scanline_resample_nearest_RGB (dest->pixels + i * dest->stride,
164         src->pixels + j * src->stride, src->width, dest->width, &xacc,
165         x_increment);
166
167     acc += y_increment;
168   }
169 }
170
171 void
172 vs_image_scale_linear_RGB (const VSImage * dest, const VSImage * src,
173     uint8_t * tmpbuf)
174 {
175   int acc;
176   int y_increment;
177   int x_increment;
178   uint8_t *tmp1;
179   uint8_t *tmp2;
180   int y1;
181   int y2;
182   int i;
183   int j;
184   int x;
185   int dest_size;
186   int xacc;
187
188   if (dest->height == 1)
189     y_increment = 0;
190   else
191     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
192
193   if (dest->width == 1)
194     x_increment = 0;
195   else
196     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
197
198   dest_size = dest->width * 3;
199
200   tmp1 = tmpbuf;
201   tmp2 = tmpbuf + dest_size;
202
203   acc = 0;
204   xacc = 0;
205   y2 = -1;
206   vs_scanline_resample_linear_RGB (tmp1, src->pixels, src->width, dest->width,
207       &xacc, x_increment);
208   y1 = 0;
209   for (i = 0; i < dest->height; i++) {
210     j = acc >> 16;
211     x = acc & 0xffff;
212
213     if (x == 0) {
214       if (j == y1) {
215         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
216       } else if (j == y2) {
217         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
218       } else {
219         xacc = 0;
220         vs_scanline_resample_linear_RGB (tmp1, src->pixels + j * src->stride,
221             src->width, dest->width, &xacc, x_increment);
222         y1 = j;
223         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
224       }
225     } else {
226       if (j == y1) {
227         if (j + 1 != y2) {
228           xacc = 0;
229           vs_scanline_resample_linear_RGB (tmp2,
230               src->pixels + (j + 1) * src->stride, src->width, dest->width,
231               &xacc, x_increment);
232           y2 = j + 1;
233         }
234         vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride,
235             tmp1, tmp2, dest->width, x);
236       } else if (j == y2) {
237         if (j + 1 != y1) {
238           xacc = 0;
239           vs_scanline_resample_linear_RGB (tmp1,
240               src->pixels + (j + 1) * src->stride, src->width, dest->width,
241               &xacc, x_increment);
242           y1 = j + 1;
243         }
244         vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride,
245             tmp2, tmp1, dest->width, x);
246       } else {
247         xacc = 0;
248         vs_scanline_resample_linear_RGB (tmp1, src->pixels + j * src->stride,
249             src->width, dest->width, &xacc, x_increment);
250         y1 = j;
251         xacc = 0;
252         vs_scanline_resample_linear_RGB (tmp2,
253             src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
254             x_increment);
255         y2 = (j + 1);
256         vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride,
257             tmp1, tmp2, dest->width, x);
258       }
259     }
260
261     acc += y_increment;
262   }
263 }
264
265 /* YUYV */
266
267 void
268 vs_image_scale_nearest_YUYV (const VSImage * dest, const VSImage * src,
269     uint8_t * tmpbuf)
270 {
271   int acc;
272   int y_increment;
273   int x_increment;
274   int i;
275   int j;
276   int xacc;
277
278   if (dest->height == 1)
279     y_increment = 0;
280   else
281     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
282
283   if (dest->width == 1)
284     x_increment = 0;
285   else
286     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
287
288   acc = 0;
289   for (i = 0; i < dest->height; i++) {
290     j = acc >> 16;
291
292     xacc = 0;
293     vs_scanline_resample_nearest_YUYV (dest->pixels + i * dest->stride,
294         src->pixels + j * src->stride, src->width, dest->width, &xacc,
295         x_increment);
296
297     acc += y_increment;
298   }
299 }
300
301 void
302 vs_image_scale_linear_YUYV (const VSImage * dest, const VSImage * src,
303     uint8_t * tmpbuf)
304 {
305   int acc;
306   int y_increment;
307   int x_increment;
308   uint8_t *tmp1;
309   uint8_t *tmp2;
310   int y1;
311   int y2;
312   int i;
313   int j;
314   int x;
315   int dest_size;
316   int xacc;
317
318   if (dest->height == 1)
319     y_increment = 0;
320   else
321     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
322
323   if (dest->width == 1)
324     x_increment = 0;
325   else
326     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
327
328   dest_size = ROUND_UP_4 (dest->width * 2);
329
330   tmp1 = tmpbuf;
331   tmp2 = tmpbuf + dest_size;
332
333   acc = 0;
334   xacc = 0;
335   y2 = -1;
336   vs_scanline_resample_linear_YUYV (tmp1, src->pixels, src->width, dest->width,
337       &xacc, x_increment);
338   y1 = 0;
339   for (i = 0; i < dest->height; i++) {
340     j = acc >> 16;
341     x = acc & 0xffff;
342
343     if (x == 0) {
344       if (j == y1) {
345         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
346       } else if (j == y2) {
347         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
348       } else {
349         xacc = 0;
350         vs_scanline_resample_linear_YUYV (tmp1, src->pixels + j * src->stride,
351             src->width, dest->width, &xacc, x_increment);
352         y1 = j;
353         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
354       }
355     } else {
356       if (j == y1) {
357         if (j + 1 != y2) {
358           xacc = 0;
359           vs_scanline_resample_linear_YUYV (tmp2,
360               src->pixels + (j + 1) * src->stride, src->width, dest->width,
361               &xacc, x_increment);
362           y2 = j + 1;
363         }
364         vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride,
365             tmp1, tmp2, dest->width, x);
366       } else if (j == y2) {
367         if (j + 1 != y1) {
368           xacc = 0;
369           vs_scanline_resample_linear_YUYV (tmp1,
370               src->pixels + (j + 1) * src->stride, src->width, dest->width,
371               &xacc, x_increment);
372           y1 = j + 1;
373         }
374         vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride,
375             tmp2, tmp1, dest->width, x);
376       } else {
377         xacc = 0;
378         vs_scanline_resample_linear_YUYV (tmp1, src->pixels + j * src->stride,
379             src->width, dest->width, &xacc, x_increment);
380         y1 = j;
381         xacc = 0;
382         vs_scanline_resample_linear_YUYV (tmp2,
383             src->pixels + (j + 1) * src->stride, src->width, dest->width,
384             &xacc, x_increment);
385         y2 = (j + 1);
386         vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride,
387             tmp1, tmp2, dest->width, x);
388       }
389     }
390
391     acc += y_increment;
392   }
393 }
394
395 /* UYVY */
396
397 void
398 vs_image_scale_nearest_UYVY (const VSImage * dest, const VSImage * src,
399     uint8_t * tmpbuf)
400 {
401   int acc;
402   int y_increment;
403   int x_increment;
404   int i;
405   int j;
406   int xacc;
407
408   if (dest->height == 1)
409     y_increment = 0;
410   else
411     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
412
413   if (dest->width == 1)
414     x_increment = 0;
415   else
416     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
417
418   acc = 0;
419   for (i = 0; i < dest->height; i++) {
420     j = acc >> 16;
421
422     xacc = 0;
423     vs_scanline_resample_nearest_UYVY (dest->pixels + i * dest->stride,
424         src->pixels + j * src->stride, src->width, dest->width, &xacc,
425         x_increment);
426
427     acc += y_increment;
428   }
429 }
430
431 void
432 vs_image_scale_linear_UYVY (const VSImage * dest, const VSImage * src,
433     uint8_t * tmpbuf)
434 {
435   int acc;
436   int y_increment;
437   int x_increment;
438   uint8_t *tmp1;
439   uint8_t *tmp2;
440   int y1;
441   int y2;
442   int i;
443   int j;
444   int x;
445   int dest_size;
446   int xacc;
447
448   if (dest->height == 1)
449     y_increment = 0;
450   else
451     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
452
453   if (dest->width == 1)
454     x_increment = 0;
455   else
456     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
457
458   dest_size = ROUND_UP_4 (dest->width * 2);
459
460   tmp1 = tmpbuf;
461   tmp2 = tmpbuf + dest_size;
462
463   acc = 0;
464   xacc = 0;
465   y2 = -1;
466   vs_scanline_resample_linear_UYVY (tmp1, src->pixels, src->width, dest->width,
467       &xacc, x_increment);
468   y1 = 0;
469   for (i = 0; i < dest->height; i++) {
470     j = acc >> 16;
471     x = acc & 0xffff;
472
473     if (x == 0) {
474       if (j == y1) {
475         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
476       } else if (j == y2) {
477         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
478       } else {
479         xacc = 0;
480         vs_scanline_resample_linear_UYVY (tmp1, src->pixels + j * src->stride,
481             src->width, dest->width, &xacc, x_increment);
482         y1 = j;
483         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
484       }
485     } else {
486       if (j == y1) {
487         if (j + 1 != y2) {
488           xacc = 0;
489           vs_scanline_resample_linear_UYVY (tmp2,
490               src->pixels + (j + 1) * src->stride, src->width, dest->width,
491               &xacc, x_increment);
492           y2 = j + 1;
493         }
494         vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride,
495             tmp1, tmp2, dest->width, x);
496       } else if (j == y2) {
497         if (j + 1 != y1) {
498           xacc = 0;
499           vs_scanline_resample_linear_UYVY (tmp1,
500               src->pixels + (j + 1) * src->stride, src->width, dest->width,
501               &xacc, x_increment);
502           y1 = j + 1;
503         }
504         vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride,
505             tmp2, tmp1, dest->width, x);
506       } else {
507         xacc = 0;
508         vs_scanline_resample_linear_UYVY (tmp1, src->pixels + j * src->stride,
509             src->width, dest->width, &xacc, x_increment);
510         y1 = j;
511         xacc = 0;
512         vs_scanline_resample_linear_UYVY (tmp2,
513             src->pixels + (j + 1) * src->stride, src->width, dest->width,
514             &xacc, x_increment);
515         y2 = (j + 1);
516         vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride,
517             tmp1, tmp2, dest->width, x);
518       }
519     }
520
521     acc += y_increment;
522   }
523 }
524
525 /* NV12 */
526
527 void
528 vs_image_scale_nearest_NV12 (const VSImage * dest, const VSImage * src,
529     uint8_t * tmpbuf)
530 {
531   int acc;
532   int y_increment;
533   int x_increment;
534   int i;
535   int j;
536   int xacc;
537
538   if (dest->height == 1)
539     y_increment = 0;
540   else
541     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
542
543   if (dest->width == 1)
544     x_increment = 0;
545   else
546     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
547
548   acc = 0;
549   for (i = 0; i < dest->height; i++) {
550     j = acc >> 16;
551
552     xacc = 0;
553     vs_scanline_resample_nearest_NV12 (dest->pixels + i * dest->stride,
554         src->pixels + j * src->stride, src->width, dest->width, &xacc,
555         x_increment);
556
557     acc += y_increment;
558   }
559 }
560
561 void
562 vs_image_scale_linear_NV12 (const VSImage * dest, const VSImage * src,
563     uint8_t * tmpbuf)
564 {
565   int acc;
566   int y_increment;
567   int x_increment;
568   uint8_t *tmp1;
569   uint8_t *tmp2;
570   int y1;
571   int y2;
572   int i;
573   int j;
574   int x;
575   int dest_size;
576   int xacc;
577
578   if (dest->height == 1)
579     y_increment = 0;
580   else
581     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
582
583   if (dest->width == 1)
584     x_increment = 0;
585   else
586     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
587
588   dest_size = ROUND_UP_4 (dest->width * 2);
589
590   tmp1 = tmpbuf;
591   tmp2 = tmpbuf + dest_size;
592
593   acc = 0;
594   xacc = 0;
595   y2 = -1;
596   vs_scanline_resample_linear_NV12 (tmp1, src->pixels, src->width, dest->width,
597       &xacc, x_increment);
598   y1 = 0;
599   for (i = 0; i < dest->height; i++) {
600     j = acc >> 16;
601     x = acc & 0xffff;
602
603     if (x == 0) {
604       if (j == y1) {
605         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
606       } else if (j == y2) {
607         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
608       } else {
609         xacc = 0;
610         vs_scanline_resample_linear_NV12 (tmp1, src->pixels + j * src->stride,
611             src->width, dest->width, &xacc, x_increment);
612         y1 = j;
613         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
614       }
615     } else {
616       if (j == y1) {
617         if (j + 1 != y2) {
618           xacc = 0;
619           vs_scanline_resample_linear_NV12 (tmp2,
620               src->pixels + (j + 1) * src->stride, src->width, dest->width,
621               &xacc, x_increment);
622           y2 = j + 1;
623         }
624         vs_scanline_merge_linear_NV12 (dest->pixels + i * dest->stride,
625             tmp1, tmp2, dest->width, x);
626       } else if (j == y2) {
627         if (j + 1 != y1) {
628           xacc = 0;
629           vs_scanline_resample_linear_NV12 (tmp1,
630               src->pixels + (j + 1) * src->stride, src->width, dest->width,
631               &xacc, x_increment);
632           y1 = j + 1;
633         }
634         vs_scanline_merge_linear_NV12 (dest->pixels + i * dest->stride,
635             tmp2, tmp1, dest->width, x);
636       } else {
637         xacc = 0;
638         vs_scanline_resample_linear_NV12 (tmp1, src->pixels + j * src->stride,
639             src->width, dest->width, &xacc, x_increment);
640         y1 = j;
641         xacc = 0;
642         vs_scanline_resample_linear_NV12 (tmp2,
643             src->pixels + (j + 1) * src->stride, src->width, dest->width,
644             &xacc, x_increment);
645         y2 = (j + 1);
646         vs_scanline_merge_linear_NV12 (dest->pixels + i * dest->stride,
647             tmp1, tmp2, dest->width, x);
648       }
649     }
650
651     acc += y_increment;
652   }
653 }
654
655 /* greyscale */
656
657 void
658 vs_image_scale_nearest_Y (const VSImage * dest, const VSImage * src,
659     uint8_t * tmpbuf)
660 {
661   int acc;
662   int y_increment;
663   int x_increment;
664   int i;
665   int j;
666
667   if (dest->height == 1)
668     y_increment = 0;
669   else
670     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
671
672   if (dest->width == 1)
673     x_increment = 0;
674   else
675     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
676
677   acc = 0;
678   for (i = 0; i < dest->height; i++) {
679     j = acc >> 16;
680
681     video_scale_orc_resample_nearest_u8 (dest->pixels + i * dest->stride,
682         src->pixels + j * src->stride, 0, x_increment, dest->width);
683     acc += y_increment;
684   }
685 }
686
687 void
688 vs_image_scale_linear_Y (const VSImage * dest, const VSImage * src,
689     uint8_t * tmpbuf)
690 {
691   int acc;
692   int y_increment;
693   int x_increment;
694   uint8_t *tmp1;
695   uint8_t *tmp2;
696   int y1;
697   int y2;
698   int i;
699   int j;
700   int x;
701   int dest_size;
702
703   if (dest->height == 1)
704     y_increment = 0;
705   else
706     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
707
708   if (dest->width == 1)
709     x_increment = 0;
710   else
711     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
712
713   dest_size = dest->width;
714
715   tmp1 = tmpbuf;
716   tmp2 = tmpbuf + dest_size;
717
718   acc = 0;
719   y2 = -1;
720   video_scale_orc_resample_bilinear_u8 (tmp1, src->pixels,
721       0, x_increment, dest->width);
722   y1 = 0;
723   for (i = 0; i < dest->height; i++) {
724     j = acc >> 16;
725     x = acc & 0xffff;
726
727     if (x == 0) {
728       if (j == y1) {
729         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
730       } else if (j == y2) {
731         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
732       } else {
733         video_scale_orc_resample_bilinear_u8 (tmp1,
734             src->pixels + j * src->stride, 0, x_increment, dest->width);
735         y1 = j;
736         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
737       }
738     } else {
739       if (j == y1) {
740         if (j + 1 != y2) {
741           video_scale_orc_resample_bilinear_u8 (tmp2,
742               src->pixels + (j + 1) * src->stride, 0, x_increment, dest->width);
743           y2 = j + 1;
744         }
745         if ((x >> 8) == 0) {
746           memcpy (dest->pixels + i * dest->stride, tmp1, dest->width);
747         } else {
748           video_scale_orc_merge_linear_u8 (dest->pixels + i * dest->stride,
749               tmp1, tmp2, (x >> 8), dest->width);
750         }
751       } else if (j == y2) {
752         if (j + 1 != y1) {
753           video_scale_orc_resample_bilinear_u8 (tmp1,
754               src->pixels + (j + 1) * src->stride, 0, x_increment, dest->width);
755           y1 = j + 1;
756         }
757         if ((x >> 8) == 0) {
758           memcpy (dest->pixels + i * dest->stride, tmp2, dest->width);
759         } else {
760           video_scale_orc_merge_linear_u8 (dest->pixels + i * dest->stride,
761               tmp2, tmp1, (x >> 8), dest->width);
762         }
763       } else {
764         video_scale_orc_resample_bilinear_u8 (tmp1,
765             src->pixels + j * src->stride, 0, x_increment, dest->width);
766         y1 = j;
767         video_scale_orc_resample_bilinear_u8 (tmp2,
768             src->pixels + (j + 1) * src->stride, 0, x_increment, dest->width);
769         y2 = (j + 1);
770         if ((x >> 8) == 0) {
771           memcpy (dest->pixels + i * dest->stride, tmp1, dest->width);
772         } else {
773           video_scale_orc_merge_linear_u8 (dest->pixels + i * dest->stride,
774               tmp1, tmp2, (x >> 8), dest->width);
775         }
776       }
777     }
778
779     acc += y_increment;
780   }
781 }
782
783 void
784 vs_image_scale_nearest_Y16 (const VSImage * dest, const VSImage * src,
785     uint8_t * tmpbuf)
786 {
787   int acc;
788   int y_increment;
789   int x_increment;
790   int i;
791   int j;
792   int xacc;
793
794   if (dest->height == 1)
795     y_increment = 0;
796   else
797     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
798
799   if (dest->width == 1)
800     x_increment = 0;
801   else
802     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
803
804   acc = 0;
805   for (i = 0; i < dest->height; i++) {
806     j = acc >> 16;
807
808     xacc = 0;
809     vs_scanline_resample_nearest_Y16 (dest->pixels + i * dest->stride,
810         src->pixels + j * src->stride, src->width, dest->width, &xacc,
811         x_increment);
812
813     acc += y_increment;
814   }
815 }
816
817 void
818 vs_image_scale_linear_Y16 (const VSImage * dest, const VSImage * src,
819     uint8_t * tmpbuf)
820 {
821   int acc;
822   int y_increment;
823   int x_increment;
824   uint8_t *tmp1;
825   uint8_t *tmp2;
826   int y1;
827   int y2;
828   int i;
829   int j;
830   int x;
831   int dest_size;
832   int xacc;
833
834   if (dest->height == 1)
835     y_increment = 0;
836   else
837     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
838
839   if (dest->width == 1)
840     x_increment = 0;
841   else
842     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
843
844   dest_size = 2 * dest->width;
845
846   tmp1 = tmpbuf;
847   tmp2 = tmpbuf + dest_size;
848
849   acc = 0;
850   xacc = 0;
851   y2 = -1;
852   vs_scanline_resample_linear_Y16 (tmp1, src->pixels, src->width, dest->width,
853       &xacc, x_increment);
854   y1 = 0;
855   for (i = 0; i < dest->height; i++) {
856     j = acc >> 16;
857     x = acc & 0xffff;
858
859     if (x == 0) {
860       if (j == y1) {
861         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
862       } else if (j == y2) {
863         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
864       } else {
865         xacc = 0;
866         vs_scanline_resample_linear_Y16 (tmp1, src->pixels + j * src->stride,
867             src->width, dest->width, &xacc, x_increment);
868         y1 = j;
869         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
870       }
871     } else {
872       if (j == y1) {
873         if (j + 1 != y2) {
874           xacc = 0;
875           vs_scanline_resample_linear_Y16 (tmp2,
876               src->pixels + (j + 1) * src->stride, src->width, dest->width,
877               &xacc, x_increment);
878           y2 = j + 1;
879         }
880         vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride,
881             tmp1, tmp2, dest->width, x);
882       } else if (j == y2) {
883         if (j + 1 != y1) {
884           xacc = 0;
885           vs_scanline_resample_linear_Y16 (tmp1,
886               src->pixels + (j + 1) * src->stride, src->width, dest->width,
887               &xacc, x_increment);
888           y1 = j + 1;
889         }
890         vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride,
891             tmp2, tmp1, dest->width, x);
892       } else {
893         xacc = 0;
894         vs_scanline_resample_linear_Y16 (tmp1, src->pixels + j * src->stride,
895             src->width, dest->width, &xacc, x_increment);
896         y1 = j;
897         xacc = 0;
898         vs_scanline_resample_linear_Y16 (tmp2,
899             src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
900             x_increment);
901         y2 = (j + 1);
902         vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride,
903             tmp1, tmp2, dest->width, x);
904       }
905     }
906
907     acc += y_increment;
908   }
909 }
910
911 /* RGB565 */
912
913 void
914 vs_image_scale_nearest_RGB565 (const VSImage * dest, const VSImage * src,
915     uint8_t * tmpbuf)
916 {
917   int acc;
918   int y_increment;
919   int x_increment;
920   int i;
921   int j;
922   int xacc;
923
924   if (dest->height == 1)
925     y_increment = 0;
926   else
927     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
928
929   if (dest->width == 1)
930     x_increment = 0;
931   else
932     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
933
934   acc = 0;
935   for (i = 0; i < dest->height; i++) {
936     j = acc >> 16;
937
938     xacc = 0;
939     vs_scanline_resample_nearest_RGB565 (dest->pixels + i * dest->stride,
940         src->pixels + j * src->stride, src->width, dest->width, &xacc,
941         x_increment);
942
943     acc += y_increment;
944   }
945 }
946
947 void
948 vs_image_scale_linear_RGB565 (const VSImage * dest, const VSImage * src,
949     uint8_t * tmpbuf)
950 {
951   int acc;
952   int y_increment;
953   int x_increment;
954   uint8_t *tmp1;
955   uint8_t *tmp2;
956   int y1;
957   int y2;
958   int i;
959   int j;
960   int x;
961   int dest_size;
962   int xacc;
963
964   if (dest->height == 1)
965     y_increment = 0;
966   else
967     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
968
969   if (dest->width == 1)
970     x_increment = 0;
971   else
972     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
973
974   dest_size = dest->width * 2;
975
976   tmp1 = tmpbuf;
977   tmp2 = tmpbuf + dest_size;
978
979   acc = 0;
980   xacc = 0;
981   y2 = -1;
982   vs_scanline_resample_linear_RGB565 (tmp1, src->pixels, src->width,
983       dest->width, &xacc, x_increment);
984   y1 = 0;
985   for (i = 0; i < dest->height; i++) {
986     j = acc >> 16;
987     x = acc & 0xffff;
988
989     if (x == 0) {
990       if (j == y1) {
991         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
992       } else if (j == y2) {
993         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
994       } else {
995         xacc = 0;
996         vs_scanline_resample_linear_RGB565 (tmp1, src->pixels + j * src->stride,
997             src->width, dest->width, &xacc, x_increment);
998         y1 = j;
999         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
1000       }
1001     } else {
1002       if (j == y1) {
1003         if (j + 1 != y2) {
1004           xacc = 0;
1005           vs_scanline_resample_linear_RGB565 (tmp2,
1006               src->pixels + (j + 1) * src->stride, src->width, dest->width,
1007               &xacc, x_increment);
1008           y2 = j + 1;
1009         }
1010         vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride,
1011             tmp1, tmp2, dest->width, x);
1012       } else if (j == y2) {
1013         if (j + 1 != y1) {
1014           xacc = 0;
1015           vs_scanline_resample_linear_RGB565 (tmp1,
1016               src->pixels + (j + 1) * src->stride, src->width, dest->width,
1017               &xacc, x_increment);
1018           y1 = j + 1;
1019         }
1020         vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride,
1021             tmp2, tmp1, dest->width, x);
1022       } else {
1023         xacc = 0;
1024         vs_scanline_resample_linear_RGB565 (tmp1, src->pixels + j * src->stride,
1025             src->width, dest->width, &xacc, x_increment);
1026         y1 = j;
1027         xacc = 0;
1028         vs_scanline_resample_linear_RGB565 (tmp2,
1029             src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
1030             x_increment);
1031         y2 = (j + 1);
1032         vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride,
1033             tmp1, tmp2, dest->width, x);
1034       }
1035     }
1036
1037     acc += y_increment;
1038   }
1039 }
1040
1041 /* RGB555 */
1042
1043 void
1044 vs_image_scale_nearest_RGB555 (const VSImage * dest, const VSImage * src,
1045     uint8_t * tmpbuf)
1046 {
1047   int acc;
1048   int y_increment;
1049   int x_increment;
1050   int i;
1051   int j;
1052   int xacc;
1053
1054   if (dest->height == 1)
1055     y_increment = 0;
1056   else
1057     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
1058
1059   if (dest->width == 1)
1060     x_increment = 0;
1061   else
1062     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
1063
1064   acc = 0;
1065   for (i = 0; i < dest->height; i++) {
1066     j = acc >> 16;
1067
1068     xacc = 0;
1069     vs_scanline_resample_nearest_RGB555 (dest->pixels + i * dest->stride,
1070         src->pixels + j * src->stride, src->width, dest->width, &xacc,
1071         x_increment);
1072
1073     acc += y_increment;
1074   }
1075 }
1076
1077 void
1078 vs_image_scale_linear_RGB555 (const VSImage * dest, const VSImage * src,
1079     uint8_t * tmpbuf)
1080 {
1081   int acc;
1082   int y_increment;
1083   int x_increment;
1084   uint8_t *tmp1;
1085   uint8_t *tmp2;
1086   int y1;
1087   int y2;
1088   int i;
1089   int j;
1090   int x;
1091   int dest_size;
1092   int xacc;
1093
1094   if (dest->height == 1)
1095     y_increment = 0;
1096   else
1097     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
1098
1099   if (dest->width == 1)
1100     x_increment = 0;
1101   else
1102     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
1103
1104   dest_size = dest->width * 2;
1105
1106   tmp1 = tmpbuf;
1107   tmp2 = tmpbuf + dest_size;
1108
1109   acc = 0;
1110   xacc = 0;
1111   y2 = -1;
1112   vs_scanline_resample_linear_RGB555 (tmp1, src->pixels, src->width,
1113       dest->width, &xacc, x_increment);
1114   y1 = 0;
1115   for (i = 0; i < dest->height; i++) {
1116     j = acc >> 16;
1117     x = acc & 0xffff;
1118
1119     if (x == 0) {
1120       if (j == y1) {
1121         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
1122       } else if (j == y2) {
1123         memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
1124       } else {
1125         xacc = 0;
1126         vs_scanline_resample_linear_RGB555 (tmp1, src->pixels + j * src->stride,
1127             src->width, dest->width, &xacc, x_increment);
1128         y1 = j;
1129         memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
1130       }
1131     } else {
1132       if (j == y1) {
1133         if (j + 1 != y2) {
1134           xacc = 0;
1135           vs_scanline_resample_linear_RGB555 (tmp2,
1136               src->pixels + (j + 1) * src->stride, src->width, dest->width,
1137               &xacc, x_increment);
1138           y2 = j + 1;
1139         }
1140         vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride,
1141             tmp1, tmp2, dest->width, x);
1142       } else if (j == y2) {
1143         if (j + 1 != y1) {
1144           xacc = 0;
1145           vs_scanline_resample_linear_RGB555 (tmp1,
1146               src->pixels + (j + 1) * src->stride, src->width, dest->width,
1147               &xacc, x_increment);
1148           y1 = j + 1;
1149         }
1150         vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride,
1151             tmp2, tmp1, dest->width, x);
1152       } else {
1153         xacc = 0;
1154         vs_scanline_resample_linear_RGB555 (tmp1, src->pixels + j * src->stride,
1155             src->width, dest->width, &xacc, x_increment);
1156         y1 = j;
1157         xacc = 0;
1158         vs_scanline_resample_linear_RGB555 (tmp2,
1159             src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
1160             x_increment);
1161         y2 = (j + 1);
1162         vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride,
1163             tmp1, tmp2, dest->width, x);
1164       }
1165     }
1166
1167     acc += y_increment;
1168   }
1169 }
1170
1171 void
1172 vs_image_scale_nearest_AYUV64 (const VSImage * dest, const VSImage * src,
1173     uint8_t * tmpbuf8)
1174 {
1175   int acc;
1176   int y_increment;
1177   int x_increment;
1178   int i;
1179   int j;
1180   int prev_j;
1181
1182   if (dest->height == 1)
1183     y_increment = 0;
1184   else
1185     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
1186
1187   if (dest->width == 1)
1188     x_increment = 0;
1189   else
1190     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
1191
1192
1193   acc = 0;
1194   prev_j = -1;
1195   for (i = 0; i < dest->height; i++) {
1196     j = acc >> 16;
1197
1198     if (j == prev_j) {
1199       memcpy (dest->pixels + i * dest->stride,
1200           dest->pixels + (i - 1) * dest->stride, dest->width * 8);
1201     } else {
1202       int xacc = 0;
1203       vs_scanline_resample_nearest_AYUV64 (dest->pixels + i * dest->stride,
1204           src->pixels + j * src->stride, src->width, dest->width, &xacc,
1205           x_increment);
1206     }
1207
1208     prev_j = j;
1209     acc += y_increment;
1210   }
1211 }
1212
1213 void
1214 vs_image_scale_linear_AYUV64 (const VSImage * dest, const VSImage * src,
1215     uint8_t * tmpbuf)
1216 {
1217   int acc;
1218   int y_increment;
1219   int x_increment;
1220   int y1;
1221   int i;
1222   int j;
1223   int x;
1224   int dest_size;
1225   int xacc;
1226
1227   if (dest->height == 1)
1228     y_increment = 0;
1229   else
1230     y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
1231
1232   if (dest->width == 1)
1233     x_increment = 0;
1234   else
1235     x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
1236
1237   dest_size = dest->width * 8;
1238
1239 #undef LINE
1240 #define LINE(x) ((guint16 *)((tmpbuf) + (dest_size)*((x)&1)))
1241
1242   acc = 0;
1243   xacc = 0;
1244   vs_scanline_resample_linear_AYUV64 ((guint8 *) LINE (0),
1245       src->pixels, src->width, dest->width, &xacc, x_increment);
1246   y1 = 0;
1247   for (i = 0; i < dest->height; i++) {
1248     j = acc >> 16;
1249     x = acc & 0xffff;
1250
1251     if (x == 0) {
1252       memcpy (dest->pixels + i * dest->stride, LINE (j), dest_size);
1253     } else {
1254       if (j > y1) {
1255         xacc = 0;
1256         vs_scanline_resample_linear_AYUV64 ((guint8 *) LINE (j),
1257             src->pixels + j * src->stride, src->width, dest->width, &xacc,
1258             x_increment);
1259         y1++;
1260       }
1261       if (j >= y1) {
1262         xacc = 0;
1263         vs_scanline_resample_linear_AYUV64 ((guint8 *) LINE (j + 1),
1264             src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc,
1265             x_increment);
1266         video_scale_orc_merge_linear_u16 ((guint16 *) (dest->pixels +
1267                 i * dest->stride), LINE (j), LINE (j + 1), 65536 - x, x,
1268             dest->width * 4);
1269         y1++;
1270       } else {
1271         video_scale_orc_merge_linear_u16 ((guint16 *) (dest->pixels +
1272                 i * dest->stride), LINE (j), LINE (j + 1), 65536 - x, x,
1273             dest->width * 4);
1274       }
1275     }
1276
1277     acc += y_increment;
1278   }
1279 }