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