2 * Image Scaling Functions (4 tap)
3 * Copyright (c) 2005 David A. Schleef <ds@schleef.org>
4 * Copyright (c) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
30 #include "vs_scanline.h"
34 #include <gst/math-compat.h>
38 static int16_t vs_4tap_taps[256][4];
41 static void vs_scanline_resample_4tap_Y (uint8_t * dest, uint8_t * src,
42 int n, int src_width, int *xacc, int increment);
43 static void vs_scanline_merge_4tap_Y (uint8_t * dest, uint8_t * src1,
44 uint8_t * src2, uint8_t * src3, uint8_t * src4, int n, int acc);
46 static void vs_scanline_resample_4tap_RGBA (uint8_t * dest, uint8_t * src,
47 int n, int src_width, int *xacc, int increment);
48 static void vs_scanline_merge_4tap_RGBA (uint8_t * dest, uint8_t * src1,
49 uint8_t * src2, uint8_t * src3, uint8_t * src4, int n, int acc);
51 static void vs_scanline_resample_4tap_RGB (uint8_t * dest, uint8_t * src,
52 int n, int src_width, int *xacc, int increment);
53 static void vs_scanline_merge_4tap_RGB (uint8_t * dest, uint8_t * src1,
54 uint8_t * src2, uint8_t * src3, uint8_t * src4, int n, int acc);
56 static void vs_scanline_resample_4tap_YUYV (uint8_t * dest, uint8_t * src,
57 int n, int src_width, int *xacc, int increment);
58 static void vs_scanline_merge_4tap_YUYV (uint8_t * dest, uint8_t * src1,
59 uint8_t * src2, uint8_t * src3, uint8_t * src4, int n, int acc);
61 static void vs_scanline_resample_4tap_UYVY (uint8_t * dest, uint8_t * src,
62 int n, int src_width, int *xacc, int increment);
63 static void vs_scanline_merge_4tap_UYVY (uint8_t * dest, uint8_t * src1,
64 uint8_t * src2, uint8_t * src3, uint8_t * src4, int n, int acc);
66 static void vs_scanline_resample_4tap_RGB565 (uint8_t * dest, uint8_t * src,
67 int n, int src_width, int *xacc, int increment);
68 static void vs_scanline_merge_4tap_RGB565 (uint8_t * dest, uint8_t * src1,
69 uint8_t * src2, uint8_t * src3, uint8_t * src4, int n, int acc);
71 static void vs_scanline_resample_4tap_RGB555 (uint8_t * dest, uint8_t * src,
72 int n, int src_width, int *xacc, int increment);
73 static void vs_scanline_merge_4tap_RGB555 (uint8_t * dest, uint8_t * src1,
74 uint8_t * src2, uint8_t * src3, uint8_t * src4, int n, int acc);
76 static void vs_scanline_resample_4tap_Y16 (uint8_t * dest, uint8_t * src,
77 int n, int src_width, int *xacc, int increment);
78 static void vs_scanline_merge_4tap_Y16 (uint8_t * dest, uint8_t * src1,
79 uint8_t * src2, uint8_t * src3, uint8_t * src4, int n, int acc);
81 static void vs_scanline_resample_4tap_AYUV64 (uint16_t * dest, uint16_t * src,
82 int n, int src_width, int *xacc, int increment);
83 static void vs_scanline_merge_4tap_AYUV64 (uint16_t * dest, uint16_t * src1,
84 uint16_t * src2, uint16_t * src3, uint16_t * src4, int n, int acc);
87 vs_4tap_func (double x)
101 return sin (G_PI * x) / (G_PI * x) * (1 - 0.25 * x * x);
106 return sin (G_PI * x) / (G_PI * x);
117 for (i = 0; i < 256; i++) {
118 a = vs_4tap_func (-1 - i / 256.0);
119 b = vs_4tap_func (0 - i / 256.0);
120 c = vs_4tap_func (1 - i / 256.0);
121 d = vs_4tap_func (2 - i / 256.0);
124 vs_4tap_taps[i][0] = rint ((1 << SHIFT) * (a / sum));
125 vs_4tap_taps[i][1] = rint ((1 << SHIFT) * (b / sum));
126 vs_4tap_taps[i][2] = rint ((1 << SHIFT) * (c / sum));
127 vs_4tap_taps[i][3] = rint ((1 << SHIFT) * (d / sum));
133 vs_scanline_resample_4tap_Y (uint8_t * dest, uint8_t * src,
134 int n, int src_width, int *xacc, int increment)
143 for (i = 0; i < n; i++) {
145 x = (acc & 0xff00) >> 8;
146 if (j - 1 >= 0 && j + 2 < src_width) {
147 y = vs_4tap_taps[x][0] * src[MAX (j - 1, 0)];
148 y += vs_4tap_taps[x][1] * src[j];
149 y += vs_4tap_taps[x][2] * src[j + 1];
150 y += vs_4tap_taps[x][3] * src[j + 2];
152 y = vs_4tap_taps[x][0] * src[CLAMP (j - 1, 0, src_width - 1)];
153 y += vs_4tap_taps[x][1] * src[CLAMP (j, 0, src_width - 1)];
154 y += vs_4tap_taps[x][2] * src[CLAMP (j + 1, 0, src_width - 1)];
155 y += vs_4tap_taps[x][3] * src[CLAMP (j + 2, 0, src_width - 1)];
157 y += (1 << (SHIFT - 1));
158 dest[i] = CLAMP (y >> SHIFT, 0, 255);
165 vs_scanline_merge_4tap_Y (uint8_t * dest, uint8_t * src1, uint8_t * src2,
166 uint8_t * src3, uint8_t * src4, int n, int acc)
172 acc = (acc >> 8) & 0xff;
173 a = vs_4tap_taps[acc][0];
174 b = vs_4tap_taps[acc][1];
175 c = vs_4tap_taps[acc][2];
176 d = vs_4tap_taps[acc][3];
177 for (i = 0; i < n; i++) {
182 y += (1 << (SHIFT - 1));
183 dest[i] = CLAMP (y >> SHIFT, 0, 255);
189 vs_image_scale_4tap_Y (const VSImage * dest, const VSImage * src,
200 if (dest->height == 1)
203 y_increment = ((src->height - 1) << 16) / (dest->height - 1);
205 if (dest->width == 1)
208 x_increment = ((src->width - 1) << 16) / (dest->width - 1);
211 for (i = 0; i < 4; i++) {
213 vs_scanline_resample_4tap_Y (tmpbuf + i * dest->width,
214 src->pixels + CLAMP (i, 0, src->height - 1) * src->stride, dest->width,
215 src->width, &xacc, x_increment);
219 for (i = 0; i < dest->height; i++) {
220 uint8_t *t0, *t1, *t2, *t3;
226 if (k + 3 < src->height) {
228 vs_scanline_resample_4tap_Y (tmpbuf + ((k + 3) & 3) * dest->width,
229 src->pixels + (k + 3) * src->stride,
230 dest->width, src->width, &xacc, x_increment);
234 t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->width;
235 t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->width;
236 t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->width;
237 t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->width;
238 vs_scanline_merge_4tap_Y (dest->pixels + i * dest->stride,
239 t0, t1, t2, t3, dest->width, yacc & 0xffff);
246 vs_scanline_resample_4tap_Y16 (uint8_t * dest, uint8_t * src,
247 int n, int src_width, int *xacc, int increment)
254 uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src;
257 for (i = 0; i < n; i++) {
259 x = (acc & 0xff00) >> 8;
260 if (j - 1 >= 0 && j + 2 < src_width) {
261 y = vs_4tap_taps[x][0] * s[MAX (j - 1, 0)];
262 y += vs_4tap_taps[x][1] * s[j];
263 y += vs_4tap_taps[x][2] * s[j + 1];
264 y += vs_4tap_taps[x][3] * s[j + 2];
266 y = vs_4tap_taps[x][0] * s[CLAMP (j - 1, 0, src_width - 1)];
267 y += vs_4tap_taps[x][1] * s[CLAMP (j, 0, src_width - 1)];
268 y += vs_4tap_taps[x][2] * s[CLAMP (j + 1, 0, src_width - 1)];
269 y += vs_4tap_taps[x][3] * s[CLAMP (j + 2, 0, src_width - 1)];
271 y += (1 << (SHIFT - 1));
272 d[i] = CLAMP (y >> SHIFT, 0, 65535);
279 vs_scanline_merge_4tap_Y16 (uint8_t * dest, uint8_t * src1, uint8_t * src2,
280 uint8_t * src3, uint8_t * src4, int n, int acc)
285 uint16_t *de = (uint16_t *) dest, *s1 = (uint16_t *) src1;
286 uint16_t *s2 = (uint16_t *) src2, *s3 = (uint16_t *) src3;
287 uint16_t *s4 = (uint16_t *) src4;
289 acc = (acc >> 8) & 0xff;
290 a = vs_4tap_taps[acc][0];
291 b = vs_4tap_taps[acc][1];
292 c = vs_4tap_taps[acc][2];
293 d = vs_4tap_taps[acc][3];
294 for (i = 0; i < n; i++) {
299 y += (1 << (SHIFT - 1));
300 de[i] = CLAMP (y >> SHIFT, 0, 65535);
306 vs_image_scale_4tap_Y16 (const VSImage * dest, const VSImage * src,
317 if (dest->height == 1)
320 y_increment = ((src->height - 1) << 16) / (dest->height - 1);
322 if (dest->width == 1)
325 x_increment = ((src->width - 1) << 16) / (dest->width - 1);
328 for (i = 0; i < 4; i++) {
330 vs_scanline_resample_4tap_Y16 (tmpbuf + i * dest->stride,
331 src->pixels + CLAMP (i, 0, src->height - 1) * src->stride, dest->width,
332 src->width, &xacc, x_increment);
336 for (i = 0; i < dest->height; i++) {
337 uint8_t *t0, *t1, *t2, *t3;
343 if (k + 3 < src->height) {
345 vs_scanline_resample_4tap_Y16 (tmpbuf + ((k + 3) & 3) * dest->stride,
346 src->pixels + (k + 3) * src->stride,
347 dest->width, src->width, &xacc, x_increment);
351 t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
352 t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
353 t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
354 t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
355 vs_scanline_merge_4tap_Y16 (dest->pixels + i * dest->stride,
356 t0, t1, t2, t3, dest->width, yacc & 0xffff);
363 vs_scanline_resample_4tap_RGBA (uint8_t * dest, uint8_t * src,
364 int n, int src_width, int *xacc, int increment)
374 for (i = 0; i < n; i++) {
376 x = (acc & 0xffff) >> 8;
378 for (off = 0; off < 4; off++) {
379 if (j - 1 >= 0 && j + 2 < src_width) {
380 y = vs_4tap_taps[x][0] * src[MAX ((j - 1) * 4 + off, 0)];
381 y += vs_4tap_taps[x][1] * src[j * 4 + off];
382 y += vs_4tap_taps[x][2] * src[(j + 1) * 4 + off];
383 y += vs_4tap_taps[x][3] * src[(j + 2) * 4 + off];
385 y = vs_4tap_taps[x][0] *
386 src[CLAMP ((j - 1), 0, src_width - 1) * 4 + off];
387 y += vs_4tap_taps[x][1] *
388 src[CLAMP ((j + 0), 0, src_width - 1) * 4 + off];
389 y += vs_4tap_taps[x][2] *
390 src[CLAMP ((j + 1), 0, src_width - 1) * 4 + off];
391 y += vs_4tap_taps[x][3] *
392 src[CLAMP ((j + 2), 0, src_width - 1) * 4 + off];
394 y += (1 << (SHIFT - 1));
395 dest[i * 4 + off] = CLAMP (y >> SHIFT, 0, 255);
403 vs_scanline_merge_4tap_RGBA (uint8_t * dest, uint8_t * src1, uint8_t * src2,
404 uint8_t * src3, uint8_t * src4, int n, int acc)
411 acc = (acc >> 8) & 0xff;
412 a = vs_4tap_taps[acc][0];
413 b = vs_4tap_taps[acc][1];
414 c = vs_4tap_taps[acc][2];
415 d = vs_4tap_taps[acc][3];
416 for (i = 0; i < n; i++) {
417 for (off = 0; off < 4; off++) {
418 y = a * src1[i * 4 + off];
419 y += b * src2[i * 4 + off];
420 y += c * src3[i * 4 + off];
421 y += d * src4[i * 4 + off];
422 y += (1 << (SHIFT - 1));
423 dest[i * 4 + off] = CLAMP (y >> SHIFT, 0, 255);
429 vs_image_scale_4tap_RGBA (const VSImage * dest, const VSImage * src,
440 if (dest->height == 1)
443 y_increment = ((src->height - 1) << 16) / (dest->height - 1);
445 if (dest->width == 1)
448 x_increment = ((src->width - 1) << 16) / (dest->width - 1);
451 for (i = 0; i < 4; i++) {
453 vs_scanline_resample_4tap_RGBA (tmpbuf + i * dest->stride,
454 src->pixels + CLAMP (i, 0, src->height) * src->stride,
455 dest->width, src->width, &xacc, x_increment);
459 for (i = 0; i < dest->height; i++) {
460 uint8_t *t0, *t1, *t2, *t3;
466 if (k + 3 < src->height) {
468 vs_scanline_resample_4tap_RGBA (tmpbuf + ((k + 3) & 3) * dest->stride,
469 src->pixels + (k + 3) * src->stride,
470 dest->width, src->width, &xacc, x_increment);
474 t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
475 t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
476 t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
477 t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
478 vs_scanline_merge_4tap_RGBA (dest->pixels + i * dest->stride,
479 t0, t1, t2, t3, dest->width, yacc & 0xffff);
486 vs_scanline_resample_4tap_RGB (uint8_t * dest, uint8_t * src,
487 int n, int src_width, int *xacc, int increment)
497 for (i = 0; i < n; i++) {
499 x = (acc & 0xffff) >> 8;
501 for (off = 0; off < 3; off++) {
502 if (j - 1 >= 0 && j + 2 < src_width) {
503 y = vs_4tap_taps[x][0] * src[MAX ((j - 1) * 3 + off, 0)];
504 y += vs_4tap_taps[x][1] * src[j * 3 + off];
505 y += vs_4tap_taps[x][2] * src[(j + 1) * 3 + off];
506 y += vs_4tap_taps[x][3] * src[(j + 2) * 3 + off];
508 y = vs_4tap_taps[x][0] * src[CLAMP ((j - 1) * 3 + off, 0,
509 3 * (src_width - 1) + off)];
510 y += vs_4tap_taps[x][1] * src[CLAMP (j * 3 + off, 0,
511 3 * (src_width - 1) + off)];
512 y += vs_4tap_taps[x][2] * src[CLAMP ((j + 1) * 3 + off, 0,
513 3 * (src_width - 1) + off)];
514 y += vs_4tap_taps[x][3] * src[CLAMP ((j + 2) * 3 + off, 0,
515 3 * (src_width - 1) + off)];
517 y += (1 << (SHIFT - 1));
518 dest[i * 3 + off] = CLAMP (y >> SHIFT, 0, 255);
526 vs_scanline_merge_4tap_RGB (uint8_t * dest, uint8_t * src1, uint8_t * src2,
527 uint8_t * src3, uint8_t * src4, int n, int acc)
534 acc = (acc >> 8) & 0xff;
535 a = vs_4tap_taps[acc][0];
536 b = vs_4tap_taps[acc][1];
537 c = vs_4tap_taps[acc][2];
538 d = vs_4tap_taps[acc][3];
539 for (i = 0; i < n; i++) {
540 for (off = 0; off < 3; off++) {
541 y = a * src1[i * 3 + off];
542 y += b * src2[i * 3 + off];
543 y += c * src3[i * 3 + off];
544 y += d * src4[i * 3 + off];
545 y += (1 << (SHIFT - 1));
546 dest[i * 3 + off] = CLAMP (y >> SHIFT, 0, 255);
552 vs_image_scale_4tap_RGB (const VSImage * dest, const VSImage * src,
563 if (dest->height == 1)
566 y_increment = ((src->height - 1) << 16) / (dest->height - 1);
568 if (dest->width == 1)
571 x_increment = ((src->width - 1) << 16) / (dest->width - 1);
574 for (i = 0; i < 4; i++) {
576 vs_scanline_resample_4tap_RGB (tmpbuf + i * dest->stride,
577 src->pixels + CLAMP (i, 0, src->height - 1) * src->stride, dest->width,
578 src->width, &xacc, x_increment);
582 for (i = 0; i < dest->height; i++) {
583 uint8_t *t0, *t1, *t2, *t3;
589 if (k + 3 < src->height) {
591 vs_scanline_resample_4tap_RGB (tmpbuf + ((k + 3) & 3) * dest->stride,
592 src->pixels + (k + 3) * src->stride,
593 dest->width, src->width, &xacc, x_increment);
597 t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
598 t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
599 t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
600 t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
601 vs_scanline_merge_4tap_RGB (dest->pixels + i * dest->stride,
602 t0, t1, t2, t3, dest->width, yacc & 0xffff);
609 vs_scanline_resample_4tap_YUYV (uint8_t * dest, uint8_t * src,
610 int n, int src_width, int *xacc, int increment)
617 int quads = (n + 1) / 2;
618 int last_y = 2 * (src_width - 1);
620 MAX ((2 * (src_width - 1) % 4 ==
621 0) ? 2 * (src_width - 1) + 1 : 2 * (src_width - 1) - 1, 1);
623 MAX ((2 * (src_width - 1) % 4 ==
624 2) ? 2 * (src_width - 1) + 1 : 2 * (src_width - 1) - 1, 1);
627 for (i = 0; i < quads; i++) {
629 x = (acc & 0xffff) >> 8;
631 if (j - 1 >= 0 && j + 2 < src_width) {
632 y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 0 - 2, 0)];
633 y += vs_4tap_taps[x][1] * src[j * 2 + 0];
634 y += vs_4tap_taps[x][2] * src[j * 2 + 0 + 2];
635 y += vs_4tap_taps[x][3] * src[j * 2 + 0 + 4];
637 y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 0 - 2, 0, last_y)];
638 y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 0, 0, last_y)];
639 y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 0 + 2, 0, last_y)];
640 y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 0 + 4, 0, last_y)];
642 y += (1 << (SHIFT - 1));
643 dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255);
646 x = (acc & 0x1ffff) >> 9;
648 if (2 * j - 1 >= 0 && 2 * j + 4 < src_width) {
649 y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 1 - 4, 1)];
650 y += vs_4tap_taps[x][1] * src[j * 4 + 1];
651 y += vs_4tap_taps[x][2] * src[j * 4 + 1 + 4];
652 y += vs_4tap_taps[x][3] * src[j * 4 + 1 + 8];
654 y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 1 - 4, 1, last_u)];
655 y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 1, 1, last_u)];
656 y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 1 + 4, 1, last_u)];
657 y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 1 + 8, 1, last_u)];
659 y += (1 << (SHIFT - 1));
660 dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255);
663 if (2 * j - 1 >= 0 && 2 * j + 4 < src_width) {
664 y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 3 - 4, 3)];
665 y += vs_4tap_taps[x][1] * src[j * 4 + 3];
666 y += vs_4tap_taps[x][2] * src[j * 4 + 3 + 4];
667 y += vs_4tap_taps[x][3] * src[j * 4 + 3 + 8];
669 y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 3 - 4, 3, last_v)];
670 y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 3, 3, last_v)];
671 y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 3 + 4, 3, last_v)];
672 y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 3 + 8, 3, last_v)];
674 y += (1 << (SHIFT - 1));
675 dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255);
680 x = (acc & 0xffff) >> 8;
683 if (j - 1 >= 0 && j + 2 < src_width) {
684 y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 0 - 2, 0)];
685 y += vs_4tap_taps[x][1] * src[j * 2 + 0];
686 y += vs_4tap_taps[x][2] * src[j * 2 + 0 + 2];
687 y += vs_4tap_taps[x][3] * src[j * 2 + 0 + 4];
689 y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 0 - 2, 0, last_y)];
690 y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 0, 0, last_y)];
691 y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 0 + 2, 0, last_y)];
692 y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 0 + 4, 0, last_y)];
694 y += (1 << (SHIFT - 1));
695 dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255);
703 vs_scanline_merge_4tap_YUYV (uint8_t * dest, uint8_t * src1, uint8_t * src2,
704 uint8_t * src3, uint8_t * src4, int n, int acc)
709 int quads = (n + 1) / 2;
711 acc = (acc >> 8) & 0xff;
712 a = vs_4tap_taps[acc][0];
713 b = vs_4tap_taps[acc][1];
714 c = vs_4tap_taps[acc][2];
715 d = vs_4tap_taps[acc][3];
716 for (i = 0; i < quads; i++) {
717 y = a * src1[i * 4 + 0];
718 y += b * src2[i * 4 + 0];
719 y += c * src3[i * 4 + 0];
720 y += d * src4[i * 4 + 0];
721 y += (1 << (SHIFT - 1));
722 dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255);
724 y = a * src1[i * 4 + 1];
725 y += b * src2[i * 4 + 1];
726 y += c * src3[i * 4 + 1];
727 y += d * src4[i * 4 + 1];
728 y += (1 << (SHIFT - 1));
729 dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255);
732 y = a * src1[i * 4 + 2];
733 y += b * src2[i * 4 + 2];
734 y += c * src3[i * 4 + 2];
735 y += d * src4[i * 4 + 2];
736 y += (1 << (SHIFT - 1));
737 dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255);
739 y = a * src1[i * 4 + 3];
740 y += b * src2[i * 4 + 3];
741 y += c * src3[i * 4 + 3];
742 y += d * src4[i * 4 + 3];
743 y += (1 << (SHIFT - 1));
744 dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255);
750 vs_image_scale_4tap_YUYV (const VSImage * dest, const VSImage * src,
761 if (dest->height == 1)
764 y_increment = ((src->height - 1) << 16) / (dest->height - 1);
766 if (dest->width == 1)
769 x_increment = ((src->width - 1) << 16) / (dest->width - 1);
772 for (i = 0; i < 4; i++) {
774 vs_scanline_resample_4tap_YUYV (tmpbuf + i * dest->stride,
775 src->pixels + CLAMP (i, 0, src->height - 1) * src->stride, dest->width,
776 src->width, &xacc, x_increment);
780 for (i = 0; i < dest->height; i++) {
781 uint8_t *t0, *t1, *t2, *t3;
787 if (k + 3 < src->height) {
789 vs_scanline_resample_4tap_YUYV (tmpbuf + ((k + 3) & 3) * dest->stride,
790 src->pixels + (k + 3) * src->stride,
791 dest->width, src->width, &xacc, x_increment);
795 t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
796 t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
797 t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
798 t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
799 vs_scanline_merge_4tap_YUYV (dest->pixels + i * dest->stride,
800 t0, t1, t2, t3, dest->width, yacc & 0xffff);
807 vs_scanline_resample_4tap_UYVY (uint8_t * dest, uint8_t * src,
808 int n, int src_width, int *xacc, int increment)
815 int quads = (n + 1) / 2;
816 int last_y = 2 * (src_width - 1) + 1;
818 MAX ((2 * (src_width - 1) % 4 ==
819 0) ? 2 * (src_width - 1) : 2 * (src_width - 1) - 2, 0);
821 MAX ((2 * (src_width - 1) % 4 ==
822 2) ? 2 * (src_width - 1) : 2 * (src_width - 1) - 2, 0);
825 for (i = 0; i < quads; i++) {
827 x = (acc & 0xffff) >> 8;
829 if (j - 1 >= 0 && j + 2 < src_width) {
830 y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 1 - 2, 1)];
831 y += vs_4tap_taps[x][1] * src[j * 2 + 1];
832 y += vs_4tap_taps[x][2] * src[j * 2 + 1 + 2];
833 y += vs_4tap_taps[x][3] * src[j * 2 + 1 + 4];
835 y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 1 - 2, 1, last_y)];
836 y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 1, 1, last_y)];
837 y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 1 + 2, 1, last_y)];
838 y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 1 + 4, 1, last_y)];
840 y += (1 << (SHIFT - 1));
841 dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255);
844 x = (acc & 0x1ffff) >> 9;
846 if (2 * j - 2 >= 0 && 2 * j + 4 < src_width) {
847 y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 0 - 4, 0)];
848 y += vs_4tap_taps[x][1] * src[j * 4 + 0];
849 y += vs_4tap_taps[x][2] * src[j * 4 + 0 + 4];
850 y += vs_4tap_taps[x][3] * src[j * 4 + 0 + 8];
852 y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 0 - 4, 0, last_u)];
853 y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 0, 0, last_u)];
854 y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 0 + 4, 0, last_u)];
855 y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 0 + 8, 0, last_u)];
857 y += (1 << (SHIFT - 1));
858 dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255);
861 if (2 * j - 1 >= 0 && 2 * j + 4 < src_width) {
862 y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 2 - 4, 2)];
863 y += vs_4tap_taps[x][1] * src[j * 4 + 2];
864 y += vs_4tap_taps[x][2] * src[j * 4 + 2 + 4];
865 y += vs_4tap_taps[x][3] * src[j * 4 + 2 + 8];
867 y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 2 - 4, 2, last_v)];
868 y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 2, 2, last_v)];
869 y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 2 + 4, 2, last_v)];
870 y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 2 + 8, 2, last_v)];
872 y += (1 << (SHIFT - 1));
873 dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255);
878 x = (acc & 0xffff) >> 8;
881 if (j - 1 >= 0 && j + 2 < src_width) {
882 y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 1 - 2, 0)];
883 y += vs_4tap_taps[x][1] * src[j * 2 + 1];
884 y += vs_4tap_taps[x][2] * src[j * 2 + 1 + 2];
885 y += vs_4tap_taps[x][3] * src[j * 2 + 1 + 4];
887 y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 1 - 2, 1, last_y)];
888 y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 1, 1, last_y)];
889 y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 1 + 2, 1, last_y)];
890 y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 1 + 4, 1, last_y)];
892 y += (1 << (SHIFT - 1));
893 dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255);
901 vs_scanline_merge_4tap_UYVY (uint8_t * dest, uint8_t * src1, uint8_t * src2,
902 uint8_t * src3, uint8_t * src4, int n, int acc)
907 int quads = (n + 1) / 2;
909 acc = (acc >> 8) & 0xff;
910 a = vs_4tap_taps[acc][0];
911 b = vs_4tap_taps[acc][1];
912 c = vs_4tap_taps[acc][2];
913 d = vs_4tap_taps[acc][3];
914 for (i = 0; i < quads; i++) {
915 y = a * src1[i * 4 + 0];
916 y += b * src2[i * 4 + 0];
917 y += c * src3[i * 4 + 0];
918 y += d * src4[i * 4 + 0];
919 y += (1 << (SHIFT - 1));
920 dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255);
922 y = a * src1[i * 4 + 1];
923 y += b * src2[i * 4 + 1];
924 y += c * src3[i * 4 + 1];
925 y += d * src4[i * 4 + 1];
926 y += (1 << (SHIFT - 1));
927 dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255);
930 y = a * src1[i * 4 + 2];
931 y += b * src2[i * 4 + 2];
932 y += c * src3[i * 4 + 2];
933 y += d * src4[i * 4 + 2];
934 y += (1 << (SHIFT - 1));
935 dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255);
937 y = a * src1[i * 4 + 3];
938 y += b * src2[i * 4 + 3];
939 y += c * src3[i * 4 + 3];
940 y += d * src4[i * 4 + 3];
941 y += (1 << (SHIFT - 1));
942 dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255);
948 vs_image_scale_4tap_UYVY (const VSImage * dest, const VSImage * src,
959 if (dest->height == 1)
962 y_increment = ((src->height - 1) << 16) / (dest->height - 1);
964 if (dest->width == 1)
967 x_increment = ((src->width - 1) << 16) / (dest->width - 1);
970 for (i = 0; i < 4; i++) {
972 vs_scanline_resample_4tap_UYVY (tmpbuf + i * dest->stride,
973 src->pixels + CLAMP (i, 0, src->height - 1) * src->stride, dest->width,
974 src->width, &xacc, x_increment);
978 for (i = 0; i < dest->height; i++) {
979 uint8_t *t0, *t1, *t2, *t3;
985 if (k + 3 < src->height) {
987 vs_scanline_resample_4tap_UYVY (tmpbuf + ((k + 3) & 3) * dest->stride,
988 src->pixels + (k + 3) * src->stride,
989 dest->width, src->width, &xacc, x_increment);
993 t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
994 t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
995 t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
996 t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
997 vs_scanline_merge_4tap_UYVY (dest->pixels + i * dest->stride,
998 t0, t1, t2, t3, dest->width, yacc & 0xffff);
1000 yacc += y_increment;
1004 /* note that src and dest are uint16_t, and thus endian dependent */
1006 #define RGB565_R(x) (((x)&0xf800)>>8 | ((x)&0xf800)>>13)
1007 #define RGB565_G(x) (((x)&0x07e0)>>3 | ((x)&0x07e0)>>9)
1008 #define RGB565_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2)
1010 #define RGB565(r,g,b) \
1011 ((((r)<<8)&0xf800) | (((g)<<3)&0x07e0) | (((b)>>3)&0x001f))
1014 vs_scanline_resample_4tap_RGB565 (uint8_t * dest_u8, uint8_t * src_u8,
1015 int n, int src_width, int *xacc, int increment)
1021 int y, y_r, y_b, y_g;
1022 uint16_t *dest = (uint16_t *) dest_u8;
1023 uint16_t *src = (uint16_t *) src_u8;
1026 for (i = 0; i < n; i++) {
1028 x = acc & 0xffff >> 8;
1030 if (j - 1 >= 0 && j + 2 < src_width) {
1031 y = vs_4tap_taps[x][0] * RGB565_R (src[MAX ((j - 1), 0)]);
1032 y += vs_4tap_taps[x][1] * RGB565_R (src[j]);
1033 y += vs_4tap_taps[x][2] * RGB565_R (src[(j + 1)]);
1034 y += vs_4tap_taps[x][3] * RGB565_R (src[(j + 2)]);
1036 y = vs_4tap_taps[x][0] * RGB565_R (src[CLAMP ((j - 1), 0,
1038 y += vs_4tap_taps[x][1] * RGB565_R (src[CLAMP (j, 0, src_width - 1)]);
1039 y += vs_4tap_taps[x][2] * RGB565_R (src[CLAMP ((j + 1), 0,
1041 y += vs_4tap_taps[x][3] * RGB565_R (src[CLAMP ((j + 2), 0,
1044 y += (1 << (SHIFT - 1));
1045 y_r = CLAMP (y >> SHIFT, 0, 255);
1047 if (j - 1 >= 0 && j + 2 < src_width) {
1048 y = vs_4tap_taps[x][0] * RGB565_G (src[MAX ((j - 1), 0)]);
1049 y += vs_4tap_taps[x][1] * RGB565_G (src[j]);
1050 y += vs_4tap_taps[x][2] * RGB565_G (src[(j + 1)]);
1051 y += vs_4tap_taps[x][3] * RGB565_G (src[(j + 2)]);
1053 y = vs_4tap_taps[x][0] * RGB565_G (src[CLAMP ((j - 1), 0,
1055 y += vs_4tap_taps[x][1] * RGB565_G (src[CLAMP (j, 0, src_width - 1)]);
1056 y += vs_4tap_taps[x][2] * RGB565_G (src[CLAMP ((j + 1), 0,
1058 y += vs_4tap_taps[x][3] * RGB565_G (src[CLAMP ((j + 2), 0,
1061 y += (1 << (SHIFT - 1));
1062 y_g = CLAMP (y >> SHIFT, 0, 255);
1064 if (j - 1 >= 0 && j + 2 < src_width) {
1065 y = vs_4tap_taps[x][0] * RGB565_B (src[MAX ((j - 1), 0)]);
1066 y += vs_4tap_taps[x][1] * RGB565_B (src[j]);
1067 y += vs_4tap_taps[x][2] * RGB565_B (src[(j + 1)]);
1068 y += vs_4tap_taps[x][3] * RGB565_B (src[(j + 2)]);
1070 y = vs_4tap_taps[x][0] * RGB565_B (src[CLAMP ((j - 1), 0,
1072 y += vs_4tap_taps[x][1] * RGB565_B (src[CLAMP (j, 0, src_width - 1)]);
1073 y += vs_4tap_taps[x][2] * RGB565_B (src[CLAMP ((j + 1), 0,
1075 y += vs_4tap_taps[x][3] * RGB565_B (src[CLAMP ((j + 2), 0,
1078 y += (1 << (SHIFT - 1));
1079 y_b = CLAMP (y >> SHIFT, 0, 255);
1081 dest[i] = RGB565 (y_r, y_b, y_g);
1088 vs_scanline_merge_4tap_RGB565 (uint8_t * dest_u8, uint8_t * src1_u8,
1089 uint8_t * src2_u8, uint8_t * src3_u8, uint8_t * src4_u8, int n, int acc)
1092 int y, y_r, y_b, y_g;
1094 uint16_t *dest = (uint16_t *) dest_u8;
1095 uint16_t *src1 = (uint16_t *) src1_u8;
1096 uint16_t *src2 = (uint16_t *) src2_u8;
1097 uint16_t *src3 = (uint16_t *) src3_u8;
1098 uint16_t *src4 = (uint16_t *) src4_u8;
1100 acc = (acc >> 8) & 0xff;
1101 a = vs_4tap_taps[acc][0];
1102 b = vs_4tap_taps[acc][1];
1103 c = vs_4tap_taps[acc][2];
1104 d = vs_4tap_taps[acc][3];
1106 for (i = 0; i < n; i++) {
1107 y = a * RGB565_R (src1[i]);
1108 y += b * RGB565_R (src2[i]);
1109 y += c * RGB565_R (src3[i]);
1110 y += d * RGB565_R (src4[i]);
1111 y += (1 << (SHIFT - 1));
1112 y_r = CLAMP (y >> SHIFT, 0, 255);
1114 y = a * RGB565_G (src1[i]);
1115 y += b * RGB565_G (src2[i]);
1116 y += c * RGB565_G (src3[i]);
1117 y += d * RGB565_G (src4[i]);
1118 y += (1 << (SHIFT - 1));
1119 y_g = CLAMP (y >> SHIFT, 0, 255);
1121 y = a * RGB565_B (src1[i]);
1122 y += b * RGB565_B (src2[i]);
1123 y += c * RGB565_B (src3[i]);
1124 y += d * RGB565_B (src4[i]);
1125 y += (1 << (SHIFT - 1));
1126 y_b = CLAMP (y >> SHIFT, 0, 255);
1128 dest[i] = RGB565 (y_r, y_b, y_g);
1133 vs_image_scale_4tap_RGB565 (const VSImage * dest, const VSImage * src,
1144 if (dest->height == 1)
1147 y_increment = ((src->height - 1) << 16) / (dest->height - 1);
1149 if (dest->width == 1)
1152 x_increment = ((src->width - 1) << 16) / (dest->width - 1);
1155 for (i = 0; i < 4; i++) {
1157 vs_scanline_resample_4tap_RGB565 (tmpbuf + i * dest->stride,
1158 src->pixels + CLAMP (i, 0, src->height - 1) * src->stride, dest->width,
1159 src->width, &xacc, x_increment);
1163 for (i = 0; i < dest->height; i++) {
1164 uint8_t *t0, *t1, *t2, *t3;
1170 if (k + 3 < src->height) {
1172 vs_scanline_resample_4tap_RGB565 (tmpbuf + ((k + 3) & 3) * dest->stride,
1173 src->pixels + (k + 3) * src->stride,
1174 dest->width, src->width, &xacc, x_increment);
1178 t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
1179 t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
1180 t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
1181 t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
1182 vs_scanline_merge_4tap_RGB565 (dest->pixels + i * dest->stride,
1183 t0, t1, t2, t3, dest->width, yacc & 0xffff);
1185 yacc += y_increment;
1189 /* note that src and dest are uint16_t, and thus endian dependent */
1191 #define RGB555_R(x) (((x)&0x7c00)>>8 | ((x)&0x7c00)>>13)
1192 #define RGB555_G(x) (((x)&0x03e0)>>3 | ((x)&0x03e0)>>9)
1193 #define RGB555_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2)
1195 #define RGB555(r,g,b) \
1196 ((((r)<<7)&0x7c00) | (((g)<<2)&0x03e0) | (((b)>>3)&0x001f))
1199 vs_scanline_resample_4tap_RGB555 (uint8_t * dest_u8, uint8_t * src_u8,
1200 int n, int src_width, int *xacc, int increment)
1206 int y, y_r, y_b, y_g;
1207 uint16_t *dest = (uint16_t *) dest_u8;
1208 uint16_t *src = (uint16_t *) src_u8;
1211 for (i = 0; i < n; i++) {
1213 x = acc & 0xffff >> 8;
1215 if (j - 1 >= 0 && j + 2 < src_width) {
1216 y = vs_4tap_taps[x][0] * RGB555_R (src[MAX ((j - 1), 0)]);
1217 y += vs_4tap_taps[x][1] * RGB555_R (src[j]);
1218 y += vs_4tap_taps[x][2] * RGB555_R (src[(j + 1)]);
1219 y += vs_4tap_taps[x][3] * RGB555_R (src[(j + 2)]);
1221 y = vs_4tap_taps[x][0] * RGB555_R (src[CLAMP ((j - 1), 0,
1223 y += vs_4tap_taps[x][1] * RGB555_R (src[CLAMP (j, 0, src_width - 1)]);
1224 y += vs_4tap_taps[x][2] * RGB555_R (src[CLAMP ((j + 1), 0,
1226 y += vs_4tap_taps[x][3] * RGB555_R (src[CLAMP ((j + 2), 0,
1229 y += (1 << (SHIFT - 1));
1230 y_r = CLAMP (y >> SHIFT, 0, 255);
1232 if (j - 1 >= 0 && j + 2 < src_width) {
1233 y = vs_4tap_taps[x][0] * RGB555_G (src[MAX ((j - 1), 0)]);
1234 y += vs_4tap_taps[x][1] * RGB555_G (src[j]);
1235 y += vs_4tap_taps[x][2] * RGB555_G (src[(j + 1)]);
1236 y += vs_4tap_taps[x][3] * RGB555_G (src[(j + 2)]);
1238 y = vs_4tap_taps[x][0] * RGB555_G (src[CLAMP ((j - 1), 0,
1240 y += vs_4tap_taps[x][1] * RGB555_G (src[CLAMP (j, 0, src_width - 1)]);
1241 y += vs_4tap_taps[x][2] * RGB555_G (src[CLAMP ((j + 1), 0,
1243 y += vs_4tap_taps[x][3] * RGB555_G (src[CLAMP ((j + 2), 0,
1246 y += (1 << (SHIFT - 1));
1247 y_g = CLAMP (y >> SHIFT, 0, 255);
1249 if (j - 1 >= 0 && j + 2 < src_width) {
1250 y = vs_4tap_taps[x][0] * RGB555_B (src[MAX ((j - 1), 0)]);
1251 y += vs_4tap_taps[x][1] * RGB555_B (src[j]);
1252 y += vs_4tap_taps[x][2] * RGB555_B (src[(j + 1)]);
1253 y += vs_4tap_taps[x][3] * RGB555_B (src[(j + 2)]);
1255 y = vs_4tap_taps[x][0] * RGB555_B (src[CLAMP ((j - 1), 0,
1257 y += vs_4tap_taps[x][1] * RGB555_B (src[CLAMP (j, 0, src_width - 1)]);
1258 y += vs_4tap_taps[x][2] * RGB555_B (src[CLAMP ((j + 1), 0,
1260 y += vs_4tap_taps[x][3] * RGB555_B (src[CLAMP ((j + 2), 0,
1263 y += (1 << (SHIFT - 1));
1264 y_b = CLAMP (y >> SHIFT, 0, 255);
1266 dest[i] = RGB555 (y_r, y_b, y_g);
1273 vs_scanline_merge_4tap_RGB555 (uint8_t * dest_u8, uint8_t * src1_u8,
1274 uint8_t * src2_u8, uint8_t * src3_u8, uint8_t * src4_u8, int n, int acc)
1277 int y, y_r, y_b, y_g;
1279 uint16_t *dest = (uint16_t *) dest_u8;
1280 uint16_t *src1 = (uint16_t *) src1_u8;
1281 uint16_t *src2 = (uint16_t *) src2_u8;
1282 uint16_t *src3 = (uint16_t *) src3_u8;
1283 uint16_t *src4 = (uint16_t *) src4_u8;
1285 acc = (acc >> 8) & 0xff;
1286 a = vs_4tap_taps[acc][0];
1287 b = vs_4tap_taps[acc][1];
1288 c = vs_4tap_taps[acc][2];
1289 d = vs_4tap_taps[acc][3];
1291 for (i = 0; i < n; i++) {
1292 y = a * RGB555_R (src1[i]);
1293 y += b * RGB555_R (src2[i]);
1294 y += c * RGB555_R (src3[i]);
1295 y += d * RGB555_R (src4[i]);
1296 y += (1 << (SHIFT - 1));
1297 y_r = CLAMP (y >> SHIFT, 0, 255);
1299 y = a * RGB555_G (src1[i]);
1300 y += b * RGB555_G (src2[i]);
1301 y += c * RGB555_G (src3[i]);
1302 y += d * RGB555_G (src4[i]);
1303 y += (1 << (SHIFT - 1));
1304 y_g = CLAMP (y >> SHIFT, 0, 255);
1306 y = a * RGB555_B (src1[i]);
1307 y += b * RGB555_B (src2[i]);
1308 y += c * RGB555_B (src3[i]);
1309 y += d * RGB555_B (src4[i]);
1310 y += (1 << (SHIFT - 1));
1311 y_b = CLAMP (y >> SHIFT, 0, 255);
1313 dest[i] = RGB555 (y_r, y_b, y_g);
1318 vs_image_scale_4tap_RGB555 (const VSImage * dest, const VSImage * src,
1329 if (dest->height == 1)
1332 y_increment = ((src->height - 1) << 16) / (dest->height - 1);
1334 if (dest->width == 1)
1337 x_increment = ((src->width - 1) << 16) / (dest->width - 1);
1340 for (i = 0; i < 4; i++) {
1342 vs_scanline_resample_4tap_RGB555 (tmpbuf + i * dest->stride,
1343 src->pixels + CLAMP (i, 0, src->height - 1) * src->stride, dest->width,
1344 src->width, &xacc, x_increment);
1348 for (i = 0; i < dest->height; i++) {
1349 uint8_t *t0, *t1, *t2, *t3;
1355 if (k + 3 < src->height) {
1357 vs_scanline_resample_4tap_RGB555 (tmpbuf + ((k + 3) & 3) * dest->stride,
1358 src->pixels + (k + 3) * src->stride,
1359 dest->width, src->width, &xacc, x_increment);
1363 t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
1364 t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
1365 t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
1366 t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
1367 vs_scanline_merge_4tap_RGB555 (dest->pixels + i * dest->stride,
1368 t0, t1, t2, t3, dest->width, yacc & 0xffff);
1370 yacc += y_increment;
1375 vs_scanline_resample_4tap_AYUV64 (uint16_t * dest, uint16_t * src,
1376 int n, int src_width, int *xacc, int increment)
1386 for (i = 0; i < n; i++) {
1388 x = (acc & 0xffff) >> 8;
1390 for (off = 0; off < 4; off++) {
1391 if (j - 1 >= 0 && j + 2 < src_width) {
1392 y = vs_4tap_taps[x][0] * src[MAX ((j - 1) * 4 + off, 0)];
1393 y += vs_4tap_taps[x][1] * src[j * 4 + off];
1394 y += vs_4tap_taps[x][2] * src[(j + 1) * 4 + off];
1395 y += vs_4tap_taps[x][3] * src[(j + 2) * 4 + off];
1397 y = vs_4tap_taps[x][0] * src[CLAMP ((j - 1) * 4 + off, 0,
1398 4 * (src_width - 1) + off)];
1399 y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + off, 0,
1400 4 * (src_width - 1) + off)];
1401 y += vs_4tap_taps[x][2] * src[CLAMP ((j + 1) * 4 + off, 0,
1402 4 * (src_width - 1) + off)];
1403 y += vs_4tap_taps[x][3] * src[CLAMP ((j + 2) * 4 + off, 0,
1404 4 * (src_width - 1) + off)];
1406 y += (1 << (SHIFT - 1));
1407 dest[i * 4 + off] = CLAMP (y >> SHIFT, 0, 255);
1415 vs_scanline_merge_4tap_AYUV64 (uint16_t * dest, uint16_t * src1,
1416 uint16_t * src2, uint16_t * src3, uint16_t * src4, int n, int acc)
1423 acc = (acc >> 8) & 0xff;
1424 a = vs_4tap_taps[acc][0];
1425 b = vs_4tap_taps[acc][1];
1426 c = vs_4tap_taps[acc][2];
1427 d = vs_4tap_taps[acc][3];
1428 for (i = 0; i < n; i++) {
1429 for (off = 0; off < 4; off++) {
1430 y = a * src1[i * 4 + off];
1431 y += b * src2[i * 4 + off];
1432 y += c * src3[i * 4 + off];
1433 y += d * src4[i * 4 + off];
1434 y += (1 << (SHIFT - 1));
1435 dest[i * 4 + off] = CLAMP (y >> SHIFT, 0, 65535);
1441 vs_image_scale_4tap_AYUV64 (const VSImage * dest, const VSImage * src,
1451 guint16 *tmpbuf = (guint16 *) tmpbuf8;
1452 /* destination stride in pixels for easier use with tmpbuf variable */
1453 int dest_pixstride = dest->stride / sizeof (guint16);
1455 if (dest->height == 1)
1458 y_increment = ((src->height - 1) << 16) / (dest->height - 1);
1460 if (dest->width == 1)
1463 x_increment = ((src->width - 1) << 16) / (dest->width - 1);
1466 for (i = 0; i < 4; i++) {
1468 vs_scanline_resample_4tap_AYUV64 (tmpbuf + i * dest_pixstride,
1469 (guint16 *) (src->pixels + CLAMP (i, 0, src->height - 1) * src->stride),
1470 dest->width, src->width, &xacc, x_increment);
1474 for (i = 0; i < dest->height; i++) {
1475 uint16_t *t0, *t1, *t2, *t3;
1481 if (k + 3 < src->height) {
1483 vs_scanline_resample_4tap_AYUV64 (tmpbuf + ((k +
1484 3) & 3) * dest_pixstride,
1485 (guint16 *) (src->pixels + (k + 3) * src->stride), dest->width,
1486 src->width, &xacc, x_increment);
1490 t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest_pixstride;
1491 t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest_pixstride;
1492 t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest_pixstride;
1493 t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest_pixstride;
1494 vs_scanline_merge_4tap_AYUV64 ((guint16 *) (dest->pixels +
1495 i * dest->stride), t0, t1, t2, t3, dest->width, yacc & 0xffff);
1497 yacc += y_increment;