typefinding: detect stand-alone SSA/ASS subtitle files
[platform/upstream/gstreamer.git] / gst / videoscale / vs_scanline.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 "vs_scanline.h"
29
30 #include "gstvideoscaleorc.h"
31 #include <gst/gst.h>
32
33 #include <string.h>
34
35 /* greyscale, i.e., single componenet */
36
37 void
38 vs_scanline_downsample_Y (uint8_t * dest, uint8_t * src, int n)
39 {
40   video_scale_orc_downsample_u8 (dest, src, n);
41 }
42
43 void
44 vs_scanline_resample_nearest_Y (uint8_t * dest, uint8_t * src, int src_width,
45     int n, int *accumulator, int increment)
46 {
47   video_scale_orc_resample_nearest_u8 (dest, src, *accumulator, increment, n);
48
49   *accumulator += n * increment;
50 }
51
52 #include <glib.h>
53 void
54 vs_scanline_resample_linear_Y (uint8_t * dest, uint8_t * src, int src_width,
55     int n, int *accumulator, int increment)
56 {
57   video_scale_orc_resample_bilinear_u8 (dest, src, *accumulator, increment, n);
58
59   *accumulator += n * increment;
60 }
61
62 void
63 vs_scanline_merge_linear_Y (uint8_t * dest, uint8_t * src1, uint8_t * src2,
64     int n, int x)
65 {
66   uint32_t value = x >> 8;
67
68   if (value == 0) {
69     memcpy (dest, src1, n);
70   } else {
71     video_scale_orc_merge_linear_u8 (dest, src1, src2, value, n);
72   }
73 }
74
75 void
76 vs_scanline_downsample_Y16 (uint8_t * dest, uint8_t * src, int n)
77 {
78   video_scale_orc_downsample_u16 ((uint16_t *) dest, (uint16_t *) src, n);
79 }
80
81 void
82 vs_scanline_resample_nearest_Y16 (uint8_t * dest, uint8_t * src, int src_width,
83     int n, int *accumulator, int increment)
84 {
85   int acc = *accumulator;
86   int i;
87   int j;
88   int x;
89   uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src;
90
91   for (i = 0; i < n; i++) {
92     j = acc >> 16;
93     x = acc & 0xffff;
94     d[i] = (x < 32768 || j + 1 >= src_width) ? s[j] : s[j + 1];
95
96     acc += increment;
97   }
98
99   *accumulator = acc;
100 }
101
102 void
103 vs_scanline_resample_linear_Y16 (uint8_t * dest, uint8_t * src, int src_width,
104     int n, int *accumulator, int increment)
105 {
106   int acc = *accumulator;
107   int i;
108   int j;
109   int x;
110   uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src;
111
112   for (i = 0; i < n; i++) {
113     j = acc >> 16;
114     x = acc & 0xffff;
115
116     if (j + 1 < src_width)
117       d[i] = (s[j] * (65536 - x) + s[j + 1] * x) >> 16;
118     else
119       d[i] = s[j];
120
121     acc += increment;
122   }
123
124   *accumulator = acc;
125 }
126
127 void
128 vs_scanline_merge_linear_Y16 (uint8_t * dest, uint8_t * src1, uint8_t * src2,
129     int n, int x)
130 {
131   uint16_t *d = (uint16_t *) dest;
132   const uint16_t *s1 = (const uint16_t *) src1;
133   const uint16_t *s2 = (const uint16_t *) src2;
134
135   if (x == 0) {
136     memcpy (d, s1, n * 2);
137   } else {
138     video_scale_orc_merge_linear_u16 (d, s1, s2, 65536 - x, x, n);
139   }
140 }
141
142 /* RGBA */
143
144 void
145 vs_scanline_downsample_RGBA (uint8_t * dest, uint8_t * src, int n)
146 {
147   video_scale_orc_downsample_u32 (dest, src, n);
148 }
149
150 void
151 vs_scanline_resample_nearest_RGBA (uint8_t * dest, uint8_t * src, int src_width,
152     int n, int *accumulator, int increment)
153 {
154   video_scale_orc_resample_nearest_u32 (dest, src, *accumulator, increment, n);
155
156   *accumulator += n * increment;
157 }
158
159 void
160 vs_scanline_resample_linear_RGBA (uint8_t * dest, uint8_t * src, int src_width,
161     int n, int *accumulator, int increment)
162 {
163   video_scale_orc_resample_bilinear_u32 (dest, src, *accumulator, increment, n);
164
165   *accumulator += n * increment;
166 }
167
168 void
169 vs_scanline_merge_linear_RGBA (uint8_t * dest, uint8_t * src1, uint8_t * src2,
170     int n, int x)
171 {
172   uint32_t value = x >> 8;
173
174   if (value == 0) {
175     memcpy (dest, src1, n * 4);
176   } else {
177     video_scale_orc_merge_linear_u8 (dest, src1, src2, value, n * 4);
178   }
179 }
180
181
182 /* RGB */
183
184 void
185 vs_scanline_downsample_RGB (uint8_t * dest, uint8_t * src, int n)
186 {
187   int i;
188
189   for (i = 0; i < n; i++) {
190     dest[i * 3 + 0] = (src[i * 6 + 0] + src[i * 6 + 3]) / 2;
191     dest[i * 3 + 1] = (src[i * 6 + 1] + src[i * 6 + 4]) / 2;
192     dest[i * 3 + 2] = (src[i * 6 + 2] + src[i * 6 + 5]) / 2;
193   }
194 }
195
196 void
197 vs_scanline_resample_nearest_RGB (uint8_t * dest, uint8_t * src, int src_width,
198     int n, int *accumulator, int increment)
199 {
200   int acc = *accumulator;
201   int i;
202   int j;
203   int x;
204
205   for (i = 0; i < n; i++) {
206     j = acc >> 16;
207     x = acc & 0xffff;
208     dest[i * 3 + 0] = (x < 32768
209         || j + 1 >= src_width) ? src[j * 3 + 0] : src[j * 3 + 3];
210     dest[i * 3 + 1] = (x < 32768
211         || j + 1 >= src_width) ? src[j * 3 + 1] : src[j * 3 + 4];
212     dest[i * 3 + 2] = (x < 32768
213         || j + 1 >= src_width) ? src[j * 3 + 2] : src[j * 3 + 5];
214
215     acc += increment;
216   }
217
218   *accumulator = acc;
219 }
220
221 void
222 vs_scanline_resample_linear_RGB (uint8_t * dest, uint8_t * src, int src_width,
223     int n, int *accumulator, int increment)
224 {
225   int acc = *accumulator;
226   int i;
227   int j;
228   int x;
229
230   for (i = 0; i < n; i++) {
231     j = acc >> 16;
232     x = acc & 0xffff;
233
234     if (j + 1 < src_width) {
235       dest[i * 3 + 0] =
236           (src[j * 3 + 0] * (65536 - x) + src[j * 3 + 3] * x) >> 16;
237       dest[i * 3 + 1] =
238           (src[j * 3 + 1] * (65536 - x) + src[j * 3 + 4] * x) >> 16;
239       dest[i * 3 + 2] =
240           (src[j * 3 + 2] * (65536 - x) + src[j * 3 + 5] * x) >> 16;
241     } else {
242       dest[i * 3 + 0] = src[j * 3 + 0];
243       dest[i * 3 + 1] = src[j * 3 + 1];
244       dest[i * 3 + 2] = src[j * 3 + 2];
245     }
246
247     acc += increment;
248   }
249
250   *accumulator = acc;
251 }
252
253 void
254 vs_scanline_merge_linear_RGB (uint8_t * dest, uint8_t * src1, uint8_t * src2,
255     int n, int x)
256 {
257   uint32_t value = x >> 8;
258
259   if (value == 0) {
260     memcpy (dest, src1, n * 3);
261   } else {
262     video_scale_orc_merge_linear_u8 (dest, src1, src2, value, n * 3);
263   }
264 }
265
266
267 /* YUYV */
268
269 /* n is the number of pixels */
270 /* increment is per Y pixel */
271
272 void
273 vs_scanline_downsample_YUYV (uint8_t * dest, uint8_t * src, int n)
274 {
275   video_scale_orc_downsample_yuyv (dest, src, n);
276 }
277
278 void
279 vs_scanline_resample_nearest_YUYV (uint8_t * dest, uint8_t * src, int src_width,
280     int n, int *accumulator, int increment)
281 {
282   int acc = *accumulator;
283   int i;
284   int j;
285   int x;
286   int quads = (n + 1) / 2;
287
288   for (i = 0; i < quads; i++) {
289     j = acc >> 16;
290     x = acc & 0xffff;
291     dest[i * 4 + 0] = (x < 32768
292         || j + 1 >= src_width) ? src[j * 2 + 0] : src[j * 2 + 2];
293
294     j = acc >> 17;
295     x = acc & 0x1ffff;
296     dest[i * 4 + 1] = (x < 65536
297         || 2 * j + 2 >= src_width) ? src[j * 4 + 1] : src[j * 4 + 5];
298
299     if (2 * i + 1 < n && 2 * j + 1 < src_width)
300       dest[i * 4 + 3] = (x < 65536
301           || 2 * j + 3 >= src_width) ? src[j * 4 + 3] : src[j * 4 + 7];
302
303     acc += increment;
304
305     j = acc >> 16;
306     x = acc & 0xffff;
307
308     if (2 * i + 1 < n && j < src_width) {
309       dest[i * 4 + 2] = (x < 32768
310           || j + 1 >= src_width) ? src[j * 2 + 0] : src[j * 2 + 2];
311       acc += increment;
312     }
313   }
314
315   *accumulator = acc;
316 }
317
318 void
319 vs_scanline_resample_linear_YUYV (uint8_t * dest, uint8_t * src, int src_width,
320     int n, int *accumulator, int increment)
321 {
322   int acc = *accumulator;
323   int i;
324   int j;
325   int x;
326   int quads = (n + 1) / 2;
327
328   for (i = 0; i < quads; i++) {
329     j = acc >> 16;
330     x = acc & 0xffff;
331
332     if (j + 1 < src_width)
333       dest[i * 4 + 0] =
334           (src[j * 2 + 0] * (65536 - x) + src[j * 2 + 2] * x) >> 16;
335     else
336       dest[i * 4 + 0] = src[j * 2 + 0];
337
338     j = acc >> 17;
339     x = acc & 0x1ffff;
340
341     if (2 * j + 2 < src_width)
342       dest[i * 4 + 1] =
343           (src[j * 4 + 1] * (131072 - x) + src[j * 4 + 5] * x) >> 17;
344     else
345       dest[i * 4 + 1] = src[j * 4 + 1];
346
347     if (2 * i + 1 < n && 2 * j + 1 < src_width) {
348       if (2 * j + 3 < src_width)
349         dest[i * 4 + 3] =
350             (src[j * 4 + 3] * (131072 - x) + src[j * 4 + 7] * x) >> 17;
351       else
352         dest[i * 4 + 3] = src[j * 4 + 3];
353     }
354
355     acc += increment;
356
357     j = acc >> 16;
358     x = acc & 0xffff;
359
360     if (2 * i + 1 < n && j < src_width) {
361       if (j + 1 < src_width)
362         dest[i * 4 + 2] =
363             (src[j * 2 + 0] * (65536 - x) + src[j * 2 + 2] * x) >> 16;
364       else
365         dest[i * 4 + 2] = src[j * 2 + 0];
366       acc += increment;
367     }
368   }
369
370
371   *accumulator = acc;
372 }
373
374 void
375 vs_scanline_merge_linear_YUYV (uint8_t * dest, uint8_t * src1, uint8_t * src2,
376     int n, int x)
377 {
378   int quads = (n + 1) / 2;
379   uint32_t value = x >> 8;
380
381   if (value == 0) {
382     memcpy (dest, src1, quads * 4);
383   } else {
384     video_scale_orc_merge_linear_u8 (dest, src1, src2, value, quads * 4);
385   }
386 }
387
388
389 /* UYVY */
390
391 /* n is the number of bi-pixels */
392 /* increment is per Y pixel */
393
394 void
395 vs_scanline_downsample_UYVY (uint8_t * dest, uint8_t * src, int n)
396 {
397   int i;
398
399   for (i = 0; i < n; i++) {
400     dest[i * 4 + 0] = (src[i * 8 + 0] + src[i * 8 + 4]) / 2;
401     dest[i * 4 + 1] = (src[i * 8 + 1] + src[i * 8 + 3]) / 2;
402     dest[i * 4 + 2] = (src[i * 8 + 2] + src[i * 8 + 6]) / 2;
403     dest[i * 4 + 3] = (src[i * 8 + 5] + src[i * 8 + 7]) / 2;
404   }
405 }
406
407 void
408 vs_scanline_resample_nearest_UYVY (uint8_t * dest, uint8_t * src, int src_width,
409     int n, int *accumulator, int increment)
410 {
411   int acc = *accumulator;
412   int i;
413   int j;
414   int x;
415   int quads = (n + 1) / 2;
416
417   for (i = 0; i < quads; i++) {
418     j = acc >> 16;
419     x = acc & 0xffff;
420
421     dest[i * 4 + 1] = (x < 32768
422         || j + 1 >= src_width) ? src[j * 2 + 1] : src[j * 2 + 3];
423
424     j = acc >> 17;
425     x = acc & 0x1ffff;
426
427     dest[i * 4 + 0] = (x < 65536
428         || 2 * j + 2 >= src_width) ? src[j * 4 + 0] : src[j * 4 + 4];
429
430     if (2 * i + 1 < n && 2 * j + 1 < src_width)
431       dest[i * 4 + 2] = (x < 65536
432           || 2 * j + 3 >= src_width) ? src[j * 4 + 2] : src[j * 4 + 6];
433
434     acc += increment;
435
436     j = acc >> 16;
437     x = acc & 0xffff;
438
439     if (2 * i + 1 < n && j < src_width) {
440       dest[i * 4 + 3] = (x < 32768
441           || j + 1 >= src_width) ? src[j * 2 + 1] : src[j * 2 + 3];
442       acc += increment;
443     }
444   }
445
446   *accumulator = acc;
447 }
448
449 void
450 vs_scanline_resample_linear_UYVY (uint8_t * dest, uint8_t * src, int src_width,
451     int n, int *accumulator, int increment)
452 {
453   int acc = *accumulator;
454   int i;
455   int j;
456   int x;
457   int quads = (n + 1) / 2;
458
459   for (i = 0; i < quads; i++) {
460     j = acc >> 16;
461     x = acc & 0xffff;
462
463     if (j + 1 < src_width)
464       dest[i * 4 + 1] =
465           (src[j * 2 + 1] * (65536 - x) + src[j * 2 + 3] * x) >> 16;
466     else
467       dest[i * 4 + 1] = src[j * 2 + 1];
468
469     j = acc >> 17;
470     x = acc & 0x1ffff;
471     if (2 * j + 2 < src_width)
472       dest[i * 4 + 0] =
473           (src[j * 4 + 0] * (131072 - x) + src[j * 4 + 4] * x) >> 17;
474     else
475       dest[i * 4 + 0] = src[j * 4 + 0];
476
477     if (i * 2 + 1 < n && 2 * j + 1 < src_width) {
478       if (2 * j + 3 < src_width)
479         dest[i * 4 + 2] =
480             (src[j * 4 + 2] * (131072 - x) + src[j * 4 + 6] * x) >> 17;
481       else
482         dest[i * 4 + 2] = src[j * 4 + 2];
483     }
484
485     acc += increment;
486
487     j = acc >> 16;
488     x = acc & 0xffff;
489
490     if (2 * i + 1 < n && j < src_width) {
491       if (j + 1 < src_width)
492         dest[i * 4 + 3] =
493             (src[j * 2 + 1] * (65536 - x) + src[j * 2 + 3] * x) >> 16;
494       else
495         dest[i * 4 + 3] = src[j * 2 + 1];
496       acc += increment;
497     }
498   }
499
500   *accumulator = acc;
501 }
502
503 void
504 vs_scanline_merge_linear_UYVY (uint8_t * dest, uint8_t * src1,
505     uint8_t * src2, int n, int x)
506 {
507   int quads = (n + 1) / 2;
508   uint32_t value = x >> 8;
509
510   if (value == 0) {
511     memcpy (dest, src1, quads * 4);
512   } else {
513     video_scale_orc_merge_linear_u8 (dest, src1, src2, value, quads * 4);
514   }
515 }
516
517
518 /* NV12 */
519
520 /* n is the number of bi-pixels */
521
522 void
523 vs_scanline_downsample_NV12 (uint8_t * dest, uint8_t * src, int n)
524 {
525   int i;
526
527   for (i = 0; i < n; i++) {
528     dest[i * 2 + 0] = (src[i * 4 + 0] + src[i * 4 + 2]) / 2;
529     dest[i * 2 + 1] = (src[i * 4 + 1] + src[i * 4 + 3]) / 2;
530   }
531 }
532
533 void
534 vs_scanline_resample_nearest_NV12 (uint8_t * dest, uint8_t * src, int src_width,
535     int n, int *accumulator, int increment)
536 {
537   int acc = *accumulator;
538   int i;
539   int j;
540   int x;
541
542   for (i = 0; i < n; i++) {
543     j = acc >> 16;
544     x = acc & 0xffff;
545
546     dest[i * 2 + 0] = (x < 32768
547         || j + 1 >= src_width) ? src[j * 2 + 0] : src[j * 2 + 2];
548     dest[i * 2 + 1] = (x < 32768
549         || j + 1 >= src_width) ? src[j * 2 + 1] : src[j * 2 + 3];
550
551     acc += increment;
552   }
553
554   *accumulator = acc;
555 }
556
557 void
558 vs_scanline_resample_linear_NV12 (uint8_t * dest, uint8_t * src, int src_width,
559     int n, int *accumulator, int increment)
560 {
561   int acc = *accumulator;
562   int i;
563   int j;
564   int x;
565
566   for (i = 0; i < n; i++) {
567     j = acc >> 16;
568     x = acc & 0xffff;
569
570     if (j + 1 < src_width) {
571       dest[i * 2 + 0] =
572           (src[j * 2 + 0] * (65536 - x) + src[j * 2 + 2] * x) >> 16;
573       dest[i * 2 + 1] =
574           (src[j * 2 + 1] * (65536 - x) + src[j * 2 + 3] * x) >> 16;
575     } else {
576       dest[i * 4 + 0] = src[j * 2 + 0];
577       dest[i * 4 + 1] = src[j * 2 + 1];
578     }
579
580     acc += increment;
581   }
582
583   *accumulator = acc;
584 }
585
586 void
587 vs_scanline_merge_linear_NV12 (uint8_t * dest, uint8_t * src1,
588     uint8_t * src2, int n, int x)
589 {
590   uint32_t value = x >> 8;
591
592   if (value == 0) {
593     memcpy (dest, src1, n * 2);
594   } else {
595     video_scale_orc_merge_linear_u8 (dest, src1, src2, value, n * 2);
596   }
597 }
598
599
600 /* RGB565 */
601
602 /* note that src and dest are uint16_t, and thus endian dependent */
603
604 #define RGB565_R(x) (((x)&0xf800)>>8 | ((x)&0xf800)>>13)
605 #define RGB565_G(x) (((x)&0x07e0)>>3 | ((x)&0x07e0)>>9)
606 #define RGB565_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2)
607
608 #define RGB565(r,g,b) \
609   ((((r)<<8)&0xf800) | (((g)<<3)&0x07e0) | (((b)>>3)&0x001f))
610
611
612 void
613 vs_scanline_downsample_RGB565 (uint8_t * dest_u8, uint8_t * src_u8, int n)
614 {
615   uint16_t *dest = (uint16_t *) dest_u8;
616   uint16_t *src = (uint16_t *) src_u8;
617   int i;
618
619   for (i = 0; i < n; i++) {
620     dest[i] = RGB565 (
621         (RGB565_R (src[i * 2]) + RGB565_R (src[i * 2 + 1])) / 2,
622         (RGB565_G (src[i * 2]) + RGB565_G (src[i * 2 + 1])) / 2,
623         (RGB565_B (src[i * 2]) + RGB565_B (src[i * 2 + 1])) / 2);
624   }
625 }
626
627 void
628 vs_scanline_resample_nearest_RGB565 (uint8_t * dest_u8, uint8_t * src_u8,
629     int src_width, int n, int *accumulator, int increment)
630 {
631   uint16_t *dest = (uint16_t *) dest_u8;
632   uint16_t *src = (uint16_t *) src_u8;
633   int acc = *accumulator;
634   int i;
635   int j;
636   int x;
637
638   for (i = 0; i < n; i++) {
639     j = acc >> 16;
640     x = acc & 0xffff;
641     dest[i] = (x < 32768 || j + 1 >= src_width) ? src[j] : src[j + 1];
642
643     acc += increment;
644   }
645
646   *accumulator = acc;
647 }
648
649 void
650 vs_scanline_resample_linear_RGB565 (uint8_t * dest_u8, uint8_t * src_u8,
651     int src_width, int n, int *accumulator, int increment)
652 {
653   uint16_t *dest = (uint16_t *) dest_u8;
654   uint16_t *src = (uint16_t *) src_u8;
655   int acc = *accumulator;
656   int i;
657   int j;
658   int x;
659
660   for (i = 0; i < n; i++) {
661     j = acc >> 16;
662     x = acc & 0xffff;
663
664     if (j + 1 < src_width) {
665       dest[i] = RGB565 (
666           (RGB565_R (src[j]) * (65536 - x) + RGB565_R (src[j + 1]) * x) >> 16,
667           (RGB565_G (src[j]) * (65536 - x) + RGB565_G (src[j + 1]) * x) >> 16,
668           (RGB565_B (src[j]) * (65536 - x) + RGB565_B (src[j + 1]) * x) >> 16);
669     } else {
670       dest[i] = RGB565 (RGB565_R (src[j]),
671           RGB565_G (src[j]), RGB565_B (src[j]));
672     }
673
674     acc += increment;
675   }
676
677   *accumulator = acc;
678 }
679
680 void
681 vs_scanline_merge_linear_RGB565 (uint8_t * dest_u8, uint8_t * src1_u8,
682     uint8_t * src2_u8, int n, int x)
683 {
684   uint16_t *dest = (uint16_t *) dest_u8;
685   uint16_t *src1 = (uint16_t *) src1_u8;
686   uint16_t *src2 = (uint16_t *) src2_u8;
687   int i;
688
689   for (i = 0; i < n; i++) {
690     dest[i] = RGB565 (
691         (RGB565_R (src1[i]) * (65536 - x) + RGB565_R (src2[i]) * x) >> 16,
692         (RGB565_G (src1[i]) * (65536 - x) + RGB565_G (src2[i]) * x) >> 16,
693         (RGB565_B (src1[i]) * (65536 - x) + RGB565_B (src2[i]) * x) >> 16);
694   }
695 }
696
697
698 /* RGB555 */
699
700 /* note that src and dest are uint16_t, and thus endian dependent */
701
702 #define RGB555_R(x) (((x)&0x7c00)>>8 | ((x)&0x7c00)>>13)
703 #define RGB555_G(x) (((x)&0x03e0)>>3 | ((x)&0x03e0)>>9)
704 #define RGB555_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2)
705
706 #define RGB555(r,g,b) \
707   ((((r)<<7)&0x7c00) | (((g)<<3)&0x03e0) | (((b)>>3)&0x001f))
708
709
710 void
711 vs_scanline_downsample_RGB555 (uint8_t * dest_u8, uint8_t * src_u8, int n)
712 {
713   uint16_t *dest = (uint16_t *) dest_u8;
714   uint16_t *src = (uint16_t *) src_u8;
715   int i;
716
717   for (i = 0; i < n; i++) {
718     dest[i] = RGB555 (
719         (RGB555_R (src[i * 2]) + RGB555_R (src[i * 2 + 1])) / 2,
720         (RGB555_G (src[i * 2]) + RGB555_G (src[i * 2 + 1])) / 2,
721         (RGB555_B (src[i * 2]) + RGB555_B (src[i * 2 + 1])) / 2);
722   }
723 }
724
725 void
726 vs_scanline_resample_nearest_RGB555 (uint8_t * dest_u8, uint8_t * src_u8,
727     int src_width, int n, int *accumulator, int increment)
728 {
729   uint16_t *dest = (uint16_t *) dest_u8;
730   uint16_t *src = (uint16_t *) src_u8;
731   int acc = *accumulator;
732   int i;
733   int j;
734   int x;
735
736   for (i = 0; i < n; i++) {
737     j = acc >> 16;
738     x = acc & 0xffff;
739     dest[i] = (x < 32768 || j + 1 >= src_width) ? src[j] : src[j + 1];
740
741     acc += increment;
742   }
743
744   *accumulator = acc;
745 }
746
747 void
748 vs_scanline_resample_linear_RGB555 (uint8_t * dest_u8, uint8_t * src_u8,
749     int src_width, int n, int *accumulator, int increment)
750 {
751   uint16_t *dest = (uint16_t *) dest_u8;
752   uint16_t *src = (uint16_t *) src_u8;
753   int acc = *accumulator;
754   int i;
755   int j;
756   int x;
757
758   for (i = 0; i < n; i++) {
759     j = acc >> 16;
760     x = acc & 0xffff;
761
762     if (j + 1 < src_width) {
763       dest[i] = RGB555 (
764           (RGB555_R (src[j]) * (65536 - x) + RGB555_R (src[j + 1]) * x) >> 16,
765           (RGB555_G (src[j]) * (65536 - x) + RGB555_G (src[j + 1]) * x) >> 16,
766           (RGB555_B (src[j]) * (65536 - x) + RGB555_B (src[j + 1]) * x) >> 16);
767     } else {
768       dest[i] = RGB555 (RGB555_R (src[j]),
769           RGB555_G (src[j]), RGB555_B (src[j]));
770     }
771
772     acc += increment;
773   }
774
775   *accumulator = acc;
776 }
777
778 void
779 vs_scanline_merge_linear_RGB555 (uint8_t * dest_u8, uint8_t * src1_u8,
780     uint8_t * src2_u8, int n, int x)
781 {
782   uint16_t *dest = (uint16_t *) dest_u8;
783   uint16_t *src1 = (uint16_t *) src1_u8;
784   uint16_t *src2 = (uint16_t *) src2_u8;
785   int i;
786
787   for (i = 0; i < n; i++) {
788     dest[i] = RGB555 (
789         (RGB555_R (src1[i]) * (65536 - x) + RGB555_R (src2[i]) * x) >> 16,
790         (RGB555_G (src1[i]) * (65536 - x) + RGB555_G (src2[i]) * x) >> 16,
791         (RGB555_B (src1[i]) * (65536 - x) + RGB555_B (src2[i]) * x) >> 16);
792   }
793 }
794
795 void
796 vs_scanline_resample_nearest_AYUV64 (uint8_t * dest8, uint8_t * src8,
797     int src_width, int n, int *accumulator, int increment)
798 {
799   guint16 *dest = (guint16 *) dest8;
800   guint16 *src = (guint16 *) src8;
801   int acc = *accumulator;
802   int i;
803   int j;
804   int x;
805
806   for (i = 0; i < n; i++) {
807     j = acc >> 16;
808     x = acc & 0xffff;
809     dest[i * 4 + 0] = (x < 32768
810         || j + 1 >= src_width) ? src[j * 4 + 0] : src[j * 4 + 4];
811     dest[i * 4 + 1] = (x < 32768
812         || j + 1 >= src_width) ? src[j * 4 + 1] : src[j * 4 + 5];
813     dest[i * 4 + 2] = (x < 32768
814         || j + 1 >= src_width) ? src[j * 4 + 2] : src[j * 4 + 6];
815     dest[i * 4 + 3] = (x < 32768
816         || j + 1 >= src_width) ? src[j * 4 + 3] : src[j * 4 + 7];
817
818     acc += increment;
819   }
820
821   *accumulator = acc;
822 }
823
824 void
825 vs_scanline_resample_linear_AYUV64 (uint8_t * dest8, uint8_t * src8,
826     int src_width, int n, int *accumulator, int increment)
827 {
828   guint16 *dest = (guint16 *) dest8;
829   guint16 *src = (guint16 *) src8;
830   int acc = *accumulator;
831   int i;
832   int j;
833   int x;
834
835   for (i = 0; i < n; i++) {
836     j = acc >> 16;
837     x = (acc & 0xffff) >> 1;
838
839     if (j + 1 < src_width) {
840       dest[i * 4 + 0] =
841           (src[j * 3 + 0] * (32768 - x) + src[j * 4 + 4] * x) >> 15;
842       dest[i * 4 + 1] =
843           (src[j * 4 + 1] * (32768 - x) + src[j * 4 + 5] * x) >> 15;
844       dest[i * 4 + 2] =
845           (src[j * 4 + 2] * (32768 - x) + src[j * 4 + 6] * x) >> 15;
846       dest[i * 4 + 3] =
847           (src[j * 4 + 3] * (32768 - x) + src[j * 4 + 7] * x) >> 15;
848     } else {
849       dest[i * 4 + 0] = src[j * 4 + 0];
850       dest[i * 4 + 1] = src[j * 4 + 1];
851       dest[i * 4 + 2] = src[j * 4 + 2];
852       dest[i * 4 + 3] = src[j * 4 + 3];
853     }
854
855     acc += increment;
856   }
857
858   *accumulator = acc;
859 }