gst_plugins_base/gst/videoscale/vs_4tap.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
     1 /*
     1 /*
     2  * Image Scaling Functions (4 tap)
     2  * Image Scaling Functions (4 tap)
     3  * Copyright (c) 2005 David A. Schleef <ds@schleef.org>
     3  * Copyright (c) 2005 David A. Schleef <ds@schleef.org>
     4  * Copyright (c) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
       
     5  * All rights reserved.
     4  * All rights reserved.
     6  *
     5  *
     7  * Redistribution and use in source and binary forms, with or without
     6  * Redistribution and use in source and binary forms, with or without
     8  * modification, are permitted provided that the following conditions
     7  * modification, are permitted provided that the following conditions
     9  * are met:
     8  * are met:
    29 #include "vs_image.h"
    28 #include "vs_image.h"
    30 #include "vs_scanline.h"
    29 #include "vs_scanline.h"
    31 
    30 
    32 #include "vs_4tap.h"
    31 #include "vs_4tap.h"
    33 
    32 
    34 #include <liboil/liboil.h>
    33 #include <gst/liboil.h>
    35 #ifdef __SYMBIAN32__
       
    36 #include <liboil/globals.h>
       
    37 #endif
       
    38 #include <math.h>
    34 #include <math.h>
       
    35 
       
    36 
       
    37 
    39 
    38 
    40 #define SHIFT 10
    39 #define SHIFT 10
    41 
    40 
    42 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
    41 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
    43 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
    42 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
   181   int i;
   180   int i;
   182   int j;
   181   int j;
   183   int xacc;
   182   int xacc;
   184   int k;
   183   int k;
   185 
   184 
   186   if (dest->height == 1)
   185   y_increment = ((src->height - 1) << 16) / (dest->height - 1);
   187     y_increment = 0;
   186   x_increment = ((src->width - 1) << 16) / (dest->width - 1);
   188   else
       
   189     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
       
   190 
       
   191   if (dest->width == 1)
       
   192     x_increment = 0;
       
   193   else
       
   194     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
       
   195 
   187 
   196   k = 0;
   188   k = 0;
   197   for (i = 0; i < 4; i++) {
   189   for (i = 0; i < 4; i++) {
   198     xacc = 0;
   190     xacc = 0;
   199     vs_scanline_resample_4tap_Y (tmpbuf + i * dest->width,
   191     vs_scanline_resample_4tap_Y (tmpbuf + i * dest->width,
   225         t0, t1, t2, t3, dest->width, yacc & 0xffff);
   217         t0, t1, t2, t3, dest->width, yacc & 0xffff);
   226 
   218 
   227     yacc += y_increment;
   219     yacc += y_increment;
   228   }
   220   }
   229 }
   221 }
   230 #ifdef __SYMBIAN32__
       
   231 EXPORT_C
       
   232 #endif
       
   233 
       
   234 void
       
   235 vs_scanline_resample_4tap_Y16 (uint8_t * dest, uint8_t * src,
       
   236     int n, int src_width, int *xacc, int increment)
       
   237 {
       
   238   int i;
       
   239   int j;
       
   240   int acc;
       
   241   int x;
       
   242   int y;
       
   243   uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src;
       
   244 
       
   245   acc = *xacc;
       
   246   for (i = 0; i < n; i++) {
       
   247     j = acc >> 16;
       
   248     x = (acc & 0xff00) >> 8;
       
   249     if (j - 1 >= 0 && j + 2 < src_width) {
       
   250       y = vs_4tap_taps[x][0] * s[MAX (j - 1, 0)];
       
   251       y += vs_4tap_taps[x][1] * s[j];
       
   252       y += vs_4tap_taps[x][2] * s[j + 1];
       
   253       y += vs_4tap_taps[x][3] * s[j + 2];
       
   254     } else {
       
   255       y = vs_4tap_taps[x][0] * s[CLAMP (j - 1, 0, src_width - 1)];
       
   256       y += vs_4tap_taps[x][1] * s[CLAMP (j, 0, src_width - 1)];
       
   257       y += vs_4tap_taps[x][2] * s[CLAMP (j + 1, 0, src_width - 1)];
       
   258       y += vs_4tap_taps[x][3] * s[CLAMP (j + 2, 0, src_width - 1)];
       
   259     }
       
   260     y += (1 << (SHIFT - 1));
       
   261     d[i] = CLAMP (y >> SHIFT, 0, 65535);
       
   262     acc += increment;
       
   263   }
       
   264   *xacc = acc;
       
   265 }
       
   266 #ifdef __SYMBIAN32__
       
   267 EXPORT_C
       
   268 #endif
       
   269 
       
   270 void
       
   271 vs_scanline_merge_4tap_Y16 (uint8_t * dest, uint8_t * src1, uint8_t * src2,
       
   272     uint8_t * src3, uint8_t * src4, int n, int acc)
       
   273 {
       
   274   int i;
       
   275   int y;
       
   276   int a, b, c, d;
       
   277   uint16_t *de = (uint16_t *) dest, *s1 = (uint16_t *) src1;
       
   278   uint16_t *s2 = (uint16_t *) src2, *s3 = (uint16_t *) src3;
       
   279   uint16_t *s4 = (uint16_t *) src4;
       
   280 
       
   281   acc = (acc >> 8) & 0xff;
       
   282   a = vs_4tap_taps[acc][0];
       
   283   b = vs_4tap_taps[acc][1];
       
   284   c = vs_4tap_taps[acc][2];
       
   285   d = vs_4tap_taps[acc][3];
       
   286   for (i = 0; i < n; i++) {
       
   287     y = a * s1[i];
       
   288     y += b * s2[i];
       
   289     y += c * s3[i];
       
   290     y += d * s4[i];
       
   291     y += (1 << (SHIFT - 1));
       
   292     de[i] = CLAMP (y >> SHIFT, 0, 65535);
       
   293   }
       
   294 }
       
   295 #ifdef __SYMBIAN32__
       
   296 EXPORT_C
       
   297 #endif
       
   298 
       
   299 
       
   300 void
       
   301 vs_image_scale_4tap_Y16 (const VSImage * dest, const VSImage * src,
       
   302     uint8_t * tmpbuf)
       
   303 {
       
   304   int yacc;
       
   305   int y_increment;
       
   306   int x_increment;
       
   307   int i;
       
   308   int j;
       
   309   int xacc;
       
   310   int k;
       
   311 
       
   312   if (dest->height == 1)
       
   313     y_increment = 0;
       
   314   else
       
   315     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
       
   316 
       
   317   if (dest->width == 1)
       
   318     x_increment = 0;
       
   319   else
       
   320     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
       
   321 
       
   322   k = 0;
       
   323   for (i = 0; i < 4; i++) {
       
   324     xacc = 0;
       
   325     vs_scanline_resample_4tap_Y16 (tmpbuf + i * dest->stride,
       
   326         src->pixels + i * src->stride, dest->width, src->width,
       
   327         &xacc, x_increment);
       
   328   }
       
   329 
       
   330   yacc = 0;
       
   331   for (i = 0; i < dest->height; i++) {
       
   332     uint8_t *t0, *t1, *t2, *t3;
       
   333 
       
   334     j = yacc >> 16;
       
   335 
       
   336     while (j > k) {
       
   337       k++;
       
   338       if (k + 3 < src->height) {
       
   339         xacc = 0;
       
   340         vs_scanline_resample_4tap_Y16 (tmpbuf + ((k + 3) & 3) * dest->stride,
       
   341             src->pixels + (k + 3) * src->stride,
       
   342             dest->width, src->width, &xacc, x_increment);
       
   343       }
       
   344     }
       
   345 
       
   346     t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
       
   347     t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
       
   348     t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
       
   349     t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
       
   350     vs_scanline_merge_4tap_Y16 (dest->pixels + i * dest->stride,
       
   351         t0, t1, t2, t3, dest->width, yacc & 0xffff);
       
   352 
       
   353     yacc += y_increment;
       
   354   }
       
   355 }
       
   356 #ifdef __SYMBIAN32__
       
   357 EXPORT_C
       
   358 #endif
       
   359 
       
   360 
       
   361 void
       
   362 vs_scanline_resample_4tap_RGBA (uint8_t * dest, uint8_t * src,
       
   363     int n, int src_width, int *xacc, int increment)
       
   364 {
       
   365   int i;
       
   366   int j;
       
   367   int acc;
       
   368   int x;
       
   369   int y;
       
   370   int off;
       
   371 
       
   372   acc = *xacc;
       
   373   for (i = 0; i < n; i++) {
       
   374     j = acc >> 16;
       
   375     x = (acc & 0xffff) >> 8;
       
   376 
       
   377     for (off = 0; off < 4; off++) {
       
   378       if (j - 1 >= 0 && j + 2 < src_width) {
       
   379         y = vs_4tap_taps[x][0] * src[MAX ((j - 1) * 4 + off, 0)];
       
   380         y += vs_4tap_taps[x][1] * src[j * 4 + off];
       
   381         y += vs_4tap_taps[x][2] * src[(j + 1) * 4 + off];
       
   382         y += vs_4tap_taps[x][3] * src[(j + 2) * 4 + off];
       
   383       } else {
       
   384         y = vs_4tap_taps[x][0] * src[CLAMP ((j - 1) * 4 + off, 0,
       
   385                 4 * (src_width - 1) + off)];
       
   386         y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + off, 0,
       
   387                 4 * (src_width - 1) + off)];
       
   388         y += vs_4tap_taps[x][2] * src[CLAMP ((j + 1) * 4 + off, 0,
       
   389                 4 * (src_width - 1) + off)];
       
   390         y += vs_4tap_taps[x][3] * src[CLAMP ((j + 2) * 4 + off, 0,
       
   391                 4 * (src_width - 1) + off)];
       
   392       }
       
   393       y += (1 << (SHIFT - 1));
       
   394       dest[i * 4 + off] = CLAMP (y >> SHIFT, 0, 255);
       
   395     }
       
   396     acc += increment;
       
   397   }
       
   398   *xacc = acc;
       
   399 }
       
   400 #ifdef __SYMBIAN32__
       
   401 EXPORT_C
       
   402 #endif
       
   403 
       
   404 
       
   405 void
       
   406 vs_scanline_merge_4tap_RGBA (uint8_t * dest, uint8_t * src1, uint8_t * src2,
       
   407     uint8_t * src3, uint8_t * src4, int n, int acc)
       
   408 {
       
   409   int i;
       
   410   int y;
       
   411   int off;
       
   412   int a, b, c, d;
       
   413 
       
   414   acc = (acc >> 8) & 0xff;
       
   415   a = vs_4tap_taps[acc][0];
       
   416   b = vs_4tap_taps[acc][1];
       
   417   c = vs_4tap_taps[acc][2];
       
   418   d = vs_4tap_taps[acc][3];
       
   419   for (i = 0; i < n; i++) {
       
   420     for (off = 0; off < 4; off++) {
       
   421       y = a * src1[i * 4 + off];
       
   422       y += b * src2[i * 4 + off];
       
   423       y += c * src3[i * 4 + off];
       
   424       y += d * src4[i * 4 + off];
       
   425       y += (1 << (SHIFT - 1));
       
   426       dest[i * 4 + off] = CLAMP (y >> SHIFT, 0, 255);
       
   427     }
       
   428   }
       
   429 }
       
   430 #ifdef __SYMBIAN32__
       
   431 EXPORT_C
       
   432 #endif
       
   433 
       
   434 
       
   435 void
       
   436 vs_image_scale_4tap_RGBA (const VSImage * dest, const VSImage * src,
       
   437     uint8_t * tmpbuf)
       
   438 {
       
   439   int yacc;
       
   440   int y_increment;
       
   441   int x_increment;
       
   442   int i;
       
   443   int j;
       
   444   int xacc;
       
   445   int k;
       
   446 
       
   447   if (dest->height == 1)
       
   448     y_increment = 0;
       
   449   else
       
   450     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
       
   451 
       
   452   if (dest->width == 1)
       
   453     x_increment = 0;
       
   454   else
       
   455     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
       
   456 
       
   457   k = 0;
       
   458   for (i = 0; i < 4; i++) {
       
   459     xacc = 0;
       
   460     vs_scanline_resample_4tap_RGBA (tmpbuf + i * dest->stride,
       
   461         src->pixels + i * src->stride, dest->width, src->width,
       
   462         &xacc, x_increment);
       
   463   }
       
   464 
       
   465   yacc = 0;
       
   466   for (i = 0; i < dest->height; i++) {
       
   467     uint8_t *t0, *t1, *t2, *t3;
       
   468 
       
   469     j = yacc >> 16;
       
   470 
       
   471     while (j > k) {
       
   472       k++;
       
   473       if (k + 3 < src->height) {
       
   474         xacc = 0;
       
   475         vs_scanline_resample_4tap_RGBA (tmpbuf + ((k + 3) & 3) * dest->stride,
       
   476             src->pixels + (k + 3) * src->stride,
       
   477             dest->width, src->width, &xacc, x_increment);
       
   478       }
       
   479     }
       
   480 
       
   481     t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
       
   482     t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
       
   483     t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
       
   484     t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
       
   485     vs_scanline_merge_4tap_RGBA (dest->pixels + i * dest->stride,
       
   486         t0, t1, t2, t3, dest->width, yacc & 0xffff);
       
   487 
       
   488     yacc += y_increment;
       
   489   }
       
   490 }
       
   491 #ifdef __SYMBIAN32__
       
   492 EXPORT_C
       
   493 #endif
       
   494 
       
   495 
       
   496 void
       
   497 vs_scanline_resample_4tap_RGB (uint8_t * dest, uint8_t * src,
       
   498     int n, int src_width, int *xacc, int increment)
       
   499 {
       
   500   int i;
       
   501   int j;
       
   502   int acc;
       
   503   int x;
       
   504   int y;
       
   505   int off;
       
   506 
       
   507   acc = *xacc;
       
   508   for (i = 0; i < n; i++) {
       
   509     j = acc >> 16;
       
   510     x = (acc & 0xffff) >> 8;
       
   511 
       
   512     for (off = 0; off < 3; off++) {
       
   513       if (j - 1 >= 0 && j + 2 < src_width) {
       
   514         y = vs_4tap_taps[x][0] * src[MAX ((j - 1) * 3 + off, 0)];
       
   515         y += vs_4tap_taps[x][1] * src[j * 3 + off];
       
   516         y += vs_4tap_taps[x][2] * src[(j + 1) * 3 + off];
       
   517         y += vs_4tap_taps[x][3] * src[(j + 2) * 3 + off];
       
   518       } else {
       
   519         y = vs_4tap_taps[x][0] * src[CLAMP ((j - 1) * 3 + off, 0,
       
   520                 3 * (src_width - 1) + off)];
       
   521         y += vs_4tap_taps[x][1] * src[CLAMP (j * 3 + off, 0,
       
   522                 3 * (src_width - 1) + off)];
       
   523         y += vs_4tap_taps[x][2] * src[CLAMP ((j + 1) * 3 + off, 0,
       
   524                 3 * (src_width - 1) + off)];
       
   525         y += vs_4tap_taps[x][3] * src[CLAMP ((j + 2) * 3 + off, 0,
       
   526                 3 * (src_width - 1) + off)];
       
   527       }
       
   528       y += (1 << (SHIFT - 1));
       
   529       dest[i * 3 + off] = CLAMP (y >> SHIFT, 0, 255);
       
   530     }
       
   531     acc += increment;
       
   532   }
       
   533   *xacc = acc;
       
   534 }
       
   535 #ifdef __SYMBIAN32__
       
   536 EXPORT_C
       
   537 #endif
       
   538 
       
   539 
       
   540 void
       
   541 vs_scanline_merge_4tap_RGB (uint8_t * dest, uint8_t * src1, uint8_t * src2,
       
   542     uint8_t * src3, uint8_t * src4, int n, int acc)
       
   543 {
       
   544   int i;
       
   545   int y;
       
   546   int off;
       
   547   int a, b, c, d;
       
   548 
       
   549   acc = (acc >> 8) & 0xff;
       
   550   a = vs_4tap_taps[acc][0];
       
   551   b = vs_4tap_taps[acc][1];
       
   552   c = vs_4tap_taps[acc][2];
       
   553   d = vs_4tap_taps[acc][3];
       
   554   for (i = 0; i < n; i++) {
       
   555     for (off = 0; off < 3; off++) {
       
   556       y = a * src1[i * 3 + off];
       
   557       y += b * src2[i * 3 + off];
       
   558       y += c * src3[i * 3 + off];
       
   559       y += d * src4[i * 3 + off];
       
   560       y += (1 << (SHIFT - 1));
       
   561       dest[i * 3 + off] = CLAMP (y >> SHIFT, 0, 255);
       
   562     }
       
   563   }
       
   564 }
       
   565 #ifdef __SYMBIAN32__
       
   566 EXPORT_C
       
   567 #endif
       
   568 
       
   569 
       
   570 void
       
   571 vs_image_scale_4tap_RGB (const VSImage * dest, const VSImage * src,
       
   572     uint8_t * tmpbuf)
       
   573 {
       
   574   int yacc;
       
   575   int y_increment;
       
   576   int x_increment;
       
   577   int i;
       
   578   int j;
       
   579   int xacc;
       
   580   int k;
       
   581 
       
   582   if (dest->height == 1)
       
   583     y_increment = 0;
       
   584   else
       
   585     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
       
   586 
       
   587   if (dest->width == 1)
       
   588     x_increment = 0;
       
   589   else
       
   590     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
       
   591 
       
   592   k = 0;
       
   593   for (i = 0; i < 4; i++) {
       
   594     xacc = 0;
       
   595     vs_scanline_resample_4tap_RGB (tmpbuf + i * dest->stride,
       
   596         src->pixels + i * src->stride, dest->width, src->width,
       
   597         &xacc, x_increment);
       
   598   }
       
   599 
       
   600   yacc = 0;
       
   601   for (i = 0; i < dest->height; i++) {
       
   602     uint8_t *t0, *t1, *t2, *t3;
       
   603 
       
   604     j = yacc >> 16;
       
   605 
       
   606     while (j > k) {
       
   607       k++;
       
   608       if (k + 3 < src->height) {
       
   609         xacc = 0;
       
   610         vs_scanline_resample_4tap_RGB (tmpbuf + ((k + 3) & 3) * dest->stride,
       
   611             src->pixels + (k + 3) * src->stride,
       
   612             dest->width, src->width, &xacc, x_increment);
       
   613       }
       
   614     }
       
   615 
       
   616     t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
       
   617     t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
       
   618     t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
       
   619     t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
       
   620     vs_scanline_merge_4tap_RGB (dest->pixels + i * dest->stride,
       
   621         t0, t1, t2, t3, dest->width, yacc & 0xffff);
       
   622 
       
   623     yacc += y_increment;
       
   624   }
       
   625 }
       
   626 #ifdef __SYMBIAN32__
       
   627 EXPORT_C
       
   628 #endif
       
   629 
       
   630 
       
   631 void
       
   632 vs_scanline_resample_4tap_YUYV (uint8_t * dest, uint8_t * src,
       
   633     int n, int src_width, int *xacc, int increment)
       
   634 {
       
   635   int i;
       
   636   int j;
       
   637   int acc;
       
   638   int x;
       
   639   int y;
       
   640   int quads = (n + 1) / 2;
       
   641   int last_y = 2 * (src_width - 1);
       
   642   int last_u =
       
   643       MAX ((2 * (src_width - 1) % 4 ==
       
   644           0) ? 2 * (src_width - 1) + 1 : 2 * (src_width - 1) - 1, 1);
       
   645   int last_v =
       
   646       MAX ((2 * (src_width - 1) % 4 ==
       
   647           2) ? 2 * (src_width - 1) + 1 : 2 * (src_width - 1) - 1, 1);
       
   648 
       
   649   acc = *xacc;
       
   650   for (i = 0; i < quads; i++) {
       
   651     j = acc >> 16;
       
   652     x = (acc & 0xffff) >> 8;
       
   653 
       
   654     if (j - 1 >= 0 && j + 2 < src_width) {
       
   655       y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 0 - 2, 0)];
       
   656       y += vs_4tap_taps[x][1] * src[j * 2 + 0];
       
   657       y += vs_4tap_taps[x][2] * src[j * 2 + 0 + 2];
       
   658       y += vs_4tap_taps[x][3] * src[j * 2 + 0 + 4];
       
   659     } else {
       
   660       y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 0 - 2, 0, last_y)];
       
   661       y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 0, 0, last_y)];
       
   662       y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 0 + 2, 0, last_y)];
       
   663       y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 0 + 4, 0, last_y)];
       
   664     }
       
   665     y += (1 << (SHIFT - 1));
       
   666     dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255);
       
   667 
       
   668     j = acc >> 17;
       
   669     x = (acc & 0x1ffff) >> 9;
       
   670 
       
   671     if (2 * (j - 1) >= 0 && 2 * (j + 4) < src_width) {
       
   672       y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 1 - 4, 1)];
       
   673       y += vs_4tap_taps[x][1] * src[j * 4 + 1];
       
   674       y += vs_4tap_taps[x][2] * src[j * 4 + 1 + 4];
       
   675       y += vs_4tap_taps[x][3] * src[j * 4 + 1 + 8];
       
   676     } else {
       
   677       y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 1 - 4, 1, last_u)];
       
   678       y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 1, 1, last_u)];
       
   679       y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 1 + 4, 1, last_u)];
       
   680       y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 1 + 8, 1, last_u)];
       
   681     }
       
   682     y += (1 << (SHIFT - 1));
       
   683     dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255);
       
   684 
       
   685     if (2 * i + 1 < n) {
       
   686       if (2 * (j - 1) >= 0 && 2 * (j + 4) < src_width) {
       
   687         y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 3 - 4, 3)];
       
   688         y += vs_4tap_taps[x][1] * src[j * 4 + 3];
       
   689         y += vs_4tap_taps[x][2] * src[j * 4 + 3 + 4];
       
   690         y += vs_4tap_taps[x][3] * src[j * 4 + 3 + 8];
       
   691       } else {
       
   692         y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 3 - 4, 3, last_v)];
       
   693         y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 3, 3, last_v)];
       
   694         y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 3 + 4, 3, last_v)];
       
   695         y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 3 + 8, 3, last_v)];
       
   696       }
       
   697       y += (1 << (SHIFT - 1));
       
   698       dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255);
       
   699     }
       
   700 
       
   701     acc += increment;
       
   702     j = acc >> 16;
       
   703     x = (acc & 0xffff) >> 8;
       
   704 
       
   705     if (2 * i + 1 < n) {
       
   706       if (j - 1 >= 0 && j + 2 < src_width) {
       
   707         y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 0 - 2, 0)];
       
   708         y += vs_4tap_taps[x][1] * src[j * 2 + 0];
       
   709         y += vs_4tap_taps[x][2] * src[j * 2 + 0 + 2];
       
   710         y += vs_4tap_taps[x][3] * src[j * 2 + 0 + 4];
       
   711       } else {
       
   712         y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 0 - 2, 0, last_y)];
       
   713         y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 0, 0, last_y)];
       
   714         y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 0 + 2, 0, last_y)];
       
   715         y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 0 + 4, 0, last_y)];
       
   716       }
       
   717       y += (1 << (SHIFT - 1));
       
   718       dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255);
       
   719       acc += increment;
       
   720     }
       
   721   }
       
   722   *xacc = acc;
       
   723 }
       
   724 #ifdef __SYMBIAN32__
       
   725 EXPORT_C
       
   726 #endif
       
   727 
       
   728 
       
   729 void
       
   730 vs_scanline_merge_4tap_YUYV (uint8_t * dest, uint8_t * src1, uint8_t * src2,
       
   731     uint8_t * src3, uint8_t * src4, int n, int acc)
       
   732 {
       
   733   int i;
       
   734   int y;
       
   735   int a, b, c, d;
       
   736   int quads = (n + 1) / 2;
       
   737 
       
   738   acc = (acc >> 8) & 0xff;
       
   739   a = vs_4tap_taps[acc][0];
       
   740   b = vs_4tap_taps[acc][1];
       
   741   c = vs_4tap_taps[acc][2];
       
   742   d = vs_4tap_taps[acc][3];
       
   743   for (i = 0; i < quads; i++) {
       
   744     y = a * src1[i * 4 + 0];
       
   745     y += b * src2[i * 4 + 0];
       
   746     y += c * src3[i * 4 + 0];
       
   747     y += d * src4[i * 4 + 0];
       
   748     y += (1 << (SHIFT - 1));
       
   749     dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255);
       
   750 
       
   751     y = a * src1[i * 4 + 1];
       
   752     y += b * src2[i * 4 + 1];
       
   753     y += c * src3[i * 4 + 1];
       
   754     y += d * src4[i * 4 + 1];
       
   755     y += (1 << (SHIFT - 1));
       
   756     dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255);
       
   757 
       
   758     if (2 * i + 1 < n) {
       
   759       y = a * src1[i * 4 + 2];
       
   760       y += b * src2[i * 4 + 2];
       
   761       y += c * src3[i * 4 + 2];
       
   762       y += d * src4[i * 4 + 2];
       
   763       y += (1 << (SHIFT - 1));
       
   764       dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255);
       
   765 
       
   766       y = a * src1[i * 4 + 3];
       
   767       y += b * src2[i * 4 + 3];
       
   768       y += c * src3[i * 4 + 3];
       
   769       y += d * src4[i * 4 + 3];
       
   770       y += (1 << (SHIFT - 1));
       
   771       dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255);
       
   772     }
       
   773   }
       
   774 }
       
   775 #ifdef __SYMBIAN32__
       
   776 EXPORT_C
       
   777 #endif
       
   778 
       
   779 
       
   780 void
       
   781 vs_image_scale_4tap_YUYV (const VSImage * dest, const VSImage * src,
       
   782     uint8_t * tmpbuf)
       
   783 {
       
   784   int yacc;
       
   785   int y_increment;
       
   786   int x_increment;
       
   787   int i;
       
   788   int j;
       
   789   int xacc;
       
   790   int k;
       
   791 
       
   792   if (dest->height == 1)
       
   793     y_increment = 0;
       
   794   else
       
   795     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
       
   796 
       
   797   if (dest->width == 1)
       
   798     x_increment = 0;
       
   799   else
       
   800     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
       
   801 
       
   802   k = 0;
       
   803   for (i = 0; i < 4; i++) {
       
   804     xacc = 0;
       
   805     vs_scanline_resample_4tap_YUYV (tmpbuf + i * dest->stride,
       
   806         src->pixels + i * src->stride, dest->width, src->width,
       
   807         &xacc, x_increment);
       
   808   }
       
   809 
       
   810   yacc = 0;
       
   811   for (i = 0; i < dest->height; i++) {
       
   812     uint8_t *t0, *t1, *t2, *t3;
       
   813 
       
   814     j = yacc >> 16;
       
   815 
       
   816     while (j > k) {
       
   817       k++;
       
   818       if (k + 3 < src->height) {
       
   819         xacc = 0;
       
   820         vs_scanline_resample_4tap_YUYV (tmpbuf + ((k + 3) & 3) * dest->stride,
       
   821             src->pixels + (k + 3) * src->stride,
       
   822             dest->width, src->width, &xacc, x_increment);
       
   823       }
       
   824     }
       
   825 
       
   826     t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
       
   827     t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
       
   828     t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
       
   829     t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
       
   830     vs_scanline_merge_4tap_YUYV (dest->pixels + i * dest->stride,
       
   831         t0, t1, t2, t3, dest->width, yacc & 0xffff);
       
   832 
       
   833     yacc += y_increment;
       
   834   }
       
   835 }
       
   836 #ifdef __SYMBIAN32__
       
   837 EXPORT_C
       
   838 #endif
       
   839 
       
   840 
       
   841 void
       
   842 vs_scanline_resample_4tap_UYVY (uint8_t * dest, uint8_t * src,
       
   843     int n, int src_width, int *xacc, int increment)
       
   844 {
       
   845   int i;
       
   846   int j;
       
   847   int acc;
       
   848   int x;
       
   849   int y;
       
   850   int quads = (n + 1) / 2;
       
   851   int last_y = 2 * (src_width - 1) + 1;
       
   852   int last_u =
       
   853       MAX ((2 * (src_width - 1) % 4 ==
       
   854           0) ? 2 * (src_width - 1) : 2 * (src_width - 1) - 2, 0);
       
   855   int last_v =
       
   856       MAX ((2 * (src_width - 1) % 4 ==
       
   857           2) ? 2 * (src_width - 1) : 2 * (src_width - 1) - 2, 0);
       
   858 
       
   859   acc = *xacc;
       
   860   for (i = 0; i < quads; i++) {
       
   861     j = acc >> 16;
       
   862     x = (acc & 0xffff) >> 8;
       
   863 
       
   864     if (j - 1 >= 0 && j + 2 < src_width) {
       
   865       y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 1 - 2, 1)];
       
   866       y += vs_4tap_taps[x][1] * src[j * 2 + 1];
       
   867       y += vs_4tap_taps[x][2] * src[j * 2 + 1 + 2];
       
   868       y += vs_4tap_taps[x][3] * src[j * 2 + 1 + 4];
       
   869     } else {
       
   870       y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 1 - 2, 1, last_y)];
       
   871       y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 1, 1, last_y)];
       
   872       y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 1 + 2, 1, last_y)];
       
   873       y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 1 + 4, 1, last_y)];
       
   874     }
       
   875     y += (1 << (SHIFT - 1));
       
   876     dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255);
       
   877 
       
   878     j = acc >> 17;
       
   879     x = (acc & 0x1ffff) >> 9;
       
   880 
       
   881     if (2 * (j - 2) >= 0 && 2 * (j + 4) < src_width) {
       
   882       y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 0 - 4, 0)];
       
   883       y += vs_4tap_taps[x][1] * src[j * 4 + 0];
       
   884       y += vs_4tap_taps[x][2] * src[j * 4 + 0 + 4];
       
   885       y += vs_4tap_taps[x][3] * src[j * 4 + 0 + 8];
       
   886     } else {
       
   887       y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 0 - 4, 0, last_u)];
       
   888       y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 0, 0, last_u)];
       
   889       y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 0 + 4, 0, last_u)];
       
   890       y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 0 + 8, 0, last_u)];
       
   891     }
       
   892     y += (1 << (SHIFT - 1));
       
   893     dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255);
       
   894 
       
   895     if (2 * i + 1 < n) {
       
   896       if (2 * (j - 1) >= 0 && 2 * (j + 4) < src_width) {
       
   897         y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 2 - 4, 2)];
       
   898         y += vs_4tap_taps[x][1] * src[j * 4 + 2];
       
   899         y += vs_4tap_taps[x][2] * src[j * 4 + 2 + 4];
       
   900         y += vs_4tap_taps[x][3] * src[j * 4 + 2 + 8];
       
   901       } else {
       
   902         y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 2 - 4, 2, last_v)];
       
   903         y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 2, 2, last_v)];
       
   904         y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 2 + 4, 2, last_v)];
       
   905         y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 2 + 8, 2, last_v)];
       
   906       }
       
   907       y += (1 << (SHIFT - 1));
       
   908       dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255);
       
   909     }
       
   910 
       
   911     acc += increment;
       
   912     j = acc >> 16;
       
   913     x = (acc & 0xffff) >> 8;
       
   914 
       
   915     if (2 * i + 1 < n) {
       
   916       if (j - 1 >= 0 && j + 2 < src_width) {
       
   917         y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 1 - 2, 0)];
       
   918         y += vs_4tap_taps[x][1] * src[j * 2 + 1];
       
   919         y += vs_4tap_taps[x][2] * src[j * 2 + 1 + 2];
       
   920         y += vs_4tap_taps[x][3] * src[j * 2 + 1 + 4];
       
   921       } else {
       
   922         y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 1 - 2, 1, last_y)];
       
   923         y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 1, 1, last_y)];
       
   924         y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 1 + 2, 1, last_y)];
       
   925         y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 1 + 4, 1, last_y)];
       
   926       }
       
   927       y += (1 << (SHIFT - 1));
       
   928       dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255);
       
   929       acc += increment;
       
   930     }
       
   931   }
       
   932   *xacc = acc;
       
   933 }
       
   934 #ifdef __SYMBIAN32__
       
   935 EXPORT_C
       
   936 #endif
       
   937 
       
   938 
       
   939 void
       
   940 vs_scanline_merge_4tap_UYVY (uint8_t * dest, uint8_t * src1, uint8_t * src2,
       
   941     uint8_t * src3, uint8_t * src4, int n, int acc)
       
   942 {
       
   943   int i;
       
   944   int y;
       
   945   int a, b, c, d;
       
   946   int quads = (n + 1) / 2;
       
   947 
       
   948   acc = (acc >> 8) & 0xff;
       
   949   a = vs_4tap_taps[acc][0];
       
   950   b = vs_4tap_taps[acc][1];
       
   951   c = vs_4tap_taps[acc][2];
       
   952   d = vs_4tap_taps[acc][3];
       
   953   for (i = 0; i < quads; i++) {
       
   954     y = a * src1[i * 4 + 0];
       
   955     y += b * src2[i * 4 + 0];
       
   956     y += c * src3[i * 4 + 0];
       
   957     y += d * src4[i * 4 + 0];
       
   958     y += (1 << (SHIFT - 1));
       
   959     dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255);
       
   960 
       
   961     y = a * src1[i * 4 + 1];
       
   962     y += b * src2[i * 4 + 1];
       
   963     y += c * src3[i * 4 + 1];
       
   964     y += d * src4[i * 4 + 1];
       
   965     y += (1 << (SHIFT - 1));
       
   966     dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255);
       
   967 
       
   968     if (2 * i + 1 < n) {
       
   969       y = a * src1[i * 4 + 2];
       
   970       y += b * src2[i * 4 + 2];
       
   971       y += c * src3[i * 4 + 2];
       
   972       y += d * src4[i * 4 + 2];
       
   973       y += (1 << (SHIFT - 1));
       
   974       dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255);
       
   975 
       
   976       y = a * src1[i * 4 + 3];
       
   977       y += b * src2[i * 4 + 3];
       
   978       y += c * src3[i * 4 + 3];
       
   979       y += d * src4[i * 4 + 3];
       
   980       y += (1 << (SHIFT - 1));
       
   981       dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255);
       
   982     }
       
   983   }
       
   984 }
       
   985 #ifdef __SYMBIAN32__
       
   986 EXPORT_C
       
   987 #endif
       
   988 
       
   989 
       
   990 void
       
   991 vs_image_scale_4tap_UYVY (const VSImage * dest, const VSImage * src,
       
   992     uint8_t * tmpbuf)
       
   993 {
       
   994   int yacc;
       
   995   int y_increment;
       
   996   int x_increment;
       
   997   int i;
       
   998   int j;
       
   999   int xacc;
       
  1000   int k;
       
  1001 
       
  1002   if (dest->height == 1)
       
  1003     y_increment = 0;
       
  1004   else
       
  1005     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
       
  1006 
       
  1007   if (dest->width == 1)
       
  1008     x_increment = 0;
       
  1009   else
       
  1010     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
       
  1011 
       
  1012   k = 0;
       
  1013   for (i = 0; i < 4; i++) {
       
  1014     xacc = 0;
       
  1015     vs_scanline_resample_4tap_UYVY (tmpbuf + i * dest->stride,
       
  1016         src->pixels + i * src->stride, dest->width, src->width,
       
  1017         &xacc, x_increment);
       
  1018   }
       
  1019 
       
  1020   yacc = 0;
       
  1021   for (i = 0; i < dest->height; i++) {
       
  1022     uint8_t *t0, *t1, *t2, *t3;
       
  1023 
       
  1024     j = yacc >> 16;
       
  1025 
       
  1026     while (j > k) {
       
  1027       k++;
       
  1028       if (k + 3 < src->height) {
       
  1029         xacc = 0;
       
  1030         vs_scanline_resample_4tap_UYVY (tmpbuf + ((k + 3) & 3) * dest->stride,
       
  1031             src->pixels + (k + 3) * src->stride,
       
  1032             dest->width, src->width, &xacc, x_increment);
       
  1033       }
       
  1034     }
       
  1035 
       
  1036     t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
       
  1037     t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
       
  1038     t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
       
  1039     t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
       
  1040     vs_scanline_merge_4tap_UYVY (dest->pixels + i * dest->stride,
       
  1041         t0, t1, t2, t3, dest->width, yacc & 0xffff);
       
  1042 
       
  1043     yacc += y_increment;
       
  1044   }
       
  1045 }
       
  1046 
       
  1047 /* note that src and dest are uint16_t, and thus endian dependent */
       
  1048 
       
  1049 #define RGB565_R(x) (((x)&0xf800)>>8 | ((x)&0xf800)>>13)
       
  1050 #define RGB565_G(x) (((x)&0x07e0)>>3 | ((x)&0x07e0)>>9)
       
  1051 #define RGB565_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2)
       
  1052 
       
  1053 #define RGB565(r,g,b) \
       
  1054   ((((r)<<8)&0xf800) | (((g)<<3)&0x07e0) | (((b)>>3)&0x001f))
       
  1055 
       
  1056 #ifdef __SYMBIAN32__
       
  1057 EXPORT_C
       
  1058 #endif
       
  1059 
       
  1060 void
       
  1061 vs_scanline_resample_4tap_RGB565 (uint8_t * dest_u8, uint8_t * src_u8,
       
  1062     int n, int src_width, int *xacc, int increment)
       
  1063 {
       
  1064   int i;
       
  1065   int j;
       
  1066   int acc;
       
  1067   int x;
       
  1068   int y, y_r, y_b, y_g;
       
  1069   uint16_t *dest = (uint16_t *) dest_u8;
       
  1070   uint16_t *src = (uint16_t *) src_u8;
       
  1071 
       
  1072   acc = *xacc;
       
  1073   for (i = 0; i < n; i++) {
       
  1074     j = acc >> 16;
       
  1075     x = acc & 0xffff >> 8;
       
  1076 
       
  1077     if (j - 1 >= 0 && j + 2 < src_width) {
       
  1078       y = vs_4tap_taps[x][0] * RGB565_R (src[MAX ((j - 1), 0)]);
       
  1079       y += vs_4tap_taps[x][1] * RGB565_R (src[j]);
       
  1080       y += vs_4tap_taps[x][2] * RGB565_R (src[(j + 1)]);
       
  1081       y += vs_4tap_taps[x][3] * RGB565_R (src[(j + 2)]);
       
  1082     } else {
       
  1083       y = vs_4tap_taps[x][0] * RGB565_R (src[CLAMP ((j - 1), 0,
       
  1084                   src_width - 1)]);
       
  1085       y += vs_4tap_taps[x][1] * RGB565_R (src[CLAMP (j, 0, src_width - 1)]);
       
  1086       y += vs_4tap_taps[x][2] * RGB565_R (src[CLAMP ((j + 1), 0,
       
  1087                   src_width - 1)]);
       
  1088       y += vs_4tap_taps[x][3] * RGB565_R (src[CLAMP ((j + 2), 0,
       
  1089                   src_width - 1)]);
       
  1090     }
       
  1091     y += (1 << (SHIFT - 1));
       
  1092     y_r = CLAMP (y >> SHIFT, 0, 255);
       
  1093 
       
  1094     if (j - 1 >= 0 && j + 2 < src_width) {
       
  1095       y = vs_4tap_taps[x][0] * RGB565_G (src[MAX ((j - 1), 0)]);
       
  1096       y += vs_4tap_taps[x][1] * RGB565_G (src[j]);
       
  1097       y += vs_4tap_taps[x][2] * RGB565_G (src[(j + 1)]);
       
  1098       y += vs_4tap_taps[x][3] * RGB565_G (src[(j + 2)]);
       
  1099     } else {
       
  1100       y = vs_4tap_taps[x][0] * RGB565_G (src[CLAMP ((j - 1), 0,
       
  1101                   src_width - 1)]);
       
  1102       y += vs_4tap_taps[x][1] * RGB565_G (src[CLAMP (j, 0, src_width - 1)]);
       
  1103       y += vs_4tap_taps[x][2] * RGB565_G (src[CLAMP ((j + 1), 0,
       
  1104                   src_width - 1)]);
       
  1105       y += vs_4tap_taps[x][3] * RGB565_G (src[CLAMP ((j + 2), 0,
       
  1106                   src_width - 1)]);
       
  1107     }
       
  1108     y += (1 << (SHIFT - 1));
       
  1109     y_g = CLAMP (y >> SHIFT, 0, 255);
       
  1110 
       
  1111     if (j - 1 >= 0 && j + 2 < src_width) {
       
  1112       y = vs_4tap_taps[x][0] * RGB565_B (src[MAX ((j - 1), 0)]);
       
  1113       y += vs_4tap_taps[x][1] * RGB565_B (src[j]);
       
  1114       y += vs_4tap_taps[x][2] * RGB565_B (src[(j + 1)]);
       
  1115       y += vs_4tap_taps[x][3] * RGB565_B (src[(j + 2)]);
       
  1116     } else {
       
  1117       y = vs_4tap_taps[x][0] * RGB565_B (src[CLAMP ((j - 1), 0,
       
  1118                   src_width - 1)]);
       
  1119       y += vs_4tap_taps[x][1] * RGB565_B (src[CLAMP (j, 0, src_width - 1)]);
       
  1120       y += vs_4tap_taps[x][2] * RGB565_B (src[CLAMP ((j + 1), 0,
       
  1121                   src_width - 1)]);
       
  1122       y += vs_4tap_taps[x][3] * RGB565_B (src[CLAMP ((j + 2), 0,
       
  1123                   src_width - 1)]);
       
  1124     }
       
  1125     y += (1 << (SHIFT - 1));
       
  1126     y_b = CLAMP (y >> SHIFT, 0, 255);
       
  1127 
       
  1128     dest[i] = RGB565 (y_r, y_b, y_g);
       
  1129     acc += increment;
       
  1130   }
       
  1131   *xacc = acc;
       
  1132 }
       
  1133 #ifdef __SYMBIAN32__
       
  1134 EXPORT_C
       
  1135 #endif
       
  1136 
       
  1137 
       
  1138 void
       
  1139 vs_scanline_merge_4tap_RGB565 (uint8_t * dest_u8, uint8_t * src1_u8,
       
  1140     uint8_t * src2_u8, uint8_t * src3_u8, uint8_t * src4_u8, int n, int acc)
       
  1141 {
       
  1142   int i;
       
  1143   int y, y_r, y_b, y_g;
       
  1144   int a, b, c, d;
       
  1145   uint16_t *dest = (uint16_t *) dest_u8;
       
  1146   uint16_t *src1 = (uint16_t *) src1_u8;
       
  1147   uint16_t *src2 = (uint16_t *) src2_u8;
       
  1148   uint16_t *src3 = (uint16_t *) src3_u8;
       
  1149   uint16_t *src4 = (uint16_t *) src4_u8;
       
  1150 
       
  1151   acc = (acc >> 8) & 0xff;
       
  1152   a = vs_4tap_taps[acc][0];
       
  1153   b = vs_4tap_taps[acc][1];
       
  1154   c = vs_4tap_taps[acc][2];
       
  1155   d = vs_4tap_taps[acc][3];
       
  1156 
       
  1157   for (i = 0; i < n; i++) {
       
  1158     y = a * RGB565_R (src1[i]);
       
  1159     y += b * RGB565_R (src2[i]);
       
  1160     y += c * RGB565_R (src3[i]);
       
  1161     y += d * RGB565_R (src4[i]);
       
  1162     y += (1 << (SHIFT - 1));
       
  1163     y_r = CLAMP (y >> SHIFT, 0, 255);
       
  1164 
       
  1165     y = a * RGB565_G (src1[i]);
       
  1166     y += b * RGB565_G (src2[i]);
       
  1167     y += c * RGB565_G (src3[i]);
       
  1168     y += d * RGB565_G (src4[i]);
       
  1169     y += (1 << (SHIFT - 1));
       
  1170     y_g = CLAMP (y >> SHIFT, 0, 255);
       
  1171 
       
  1172     y = a * RGB565_B (src1[i]);
       
  1173     y += b * RGB565_B (src2[i]);
       
  1174     y += c * RGB565_B (src3[i]);
       
  1175     y += d * RGB565_B (src4[i]);
       
  1176     y += (1 << (SHIFT - 1));
       
  1177     y_b = CLAMP (y >> SHIFT, 0, 255);
       
  1178 
       
  1179     dest[i] = RGB565 (y_r, y_b, y_g);
       
  1180   }
       
  1181 }
       
  1182 #ifdef __SYMBIAN32__
       
  1183 EXPORT_C
       
  1184 #endif
       
  1185 
       
  1186 
       
  1187 void
       
  1188 vs_image_scale_4tap_RGB565 (const VSImage * dest, const VSImage * src,
       
  1189     uint8_t * tmpbuf)
       
  1190 {
       
  1191   int yacc;
       
  1192   int y_increment;
       
  1193   int x_increment;
       
  1194   int i;
       
  1195   int j;
       
  1196   int xacc;
       
  1197   int k;
       
  1198 
       
  1199   if (dest->height == 1)
       
  1200     y_increment = 0;
       
  1201   else
       
  1202     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
       
  1203 
       
  1204   if (dest->width == 1)
       
  1205     x_increment = 0;
       
  1206   else
       
  1207     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
       
  1208 
       
  1209   k = 0;
       
  1210   for (i = 0; i < 4; i++) {
       
  1211     xacc = 0;
       
  1212     vs_scanline_resample_4tap_RGB565 (tmpbuf + i * dest->stride,
       
  1213         src->pixels + i * src->stride, dest->width, src->width,
       
  1214         &xacc, x_increment);
       
  1215   }
       
  1216 
       
  1217   yacc = 0;
       
  1218   for (i = 0; i < dest->height; i++) {
       
  1219     uint8_t *t0, *t1, *t2, *t3;
       
  1220 
       
  1221     j = yacc >> 16;
       
  1222 
       
  1223     while (j > k) {
       
  1224       k++;
       
  1225       if (k + 3 < src->height) {
       
  1226         xacc = 0;
       
  1227         vs_scanline_resample_4tap_RGB565 (tmpbuf + ((k + 3) & 3) * dest->stride,
       
  1228             src->pixels + (k + 3) * src->stride,
       
  1229             dest->width, src->width, &xacc, x_increment);
       
  1230       }
       
  1231     }
       
  1232 
       
  1233     t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
       
  1234     t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
       
  1235     t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
       
  1236     t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
       
  1237     vs_scanline_merge_4tap_RGB565 (dest->pixels + i * dest->stride,
       
  1238         t0, t1, t2, t3, dest->width, yacc & 0xffff);
       
  1239 
       
  1240     yacc += y_increment;
       
  1241   }
       
  1242 }
       
  1243 
       
  1244 /* note that src and dest are uint16_t, and thus endian dependent */
       
  1245 
       
  1246 #define RGB555_R(x) (((x)&0x7c00)>>8 | ((x)&0x7c00)>>13)
       
  1247 #define RGB555_G(x) (((x)&0x03e0)>>3 | ((x)&0x03e0)>>9)
       
  1248 #define RGB555_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2)
       
  1249 
       
  1250 #define RGB555(r,g,b) \
       
  1251   ((((r)<<7)&0x7c00) | (((g)<<2)&0x03e0) | (((b)>>3)&0x001f))
       
  1252 
       
  1253 #ifdef __SYMBIAN32__
       
  1254 EXPORT_C
       
  1255 #endif
       
  1256 
       
  1257 void
       
  1258 vs_scanline_resample_4tap_RGB555 (uint8_t * dest_u8, uint8_t * src_u8,
       
  1259     int n, int src_width, int *xacc, int increment)
       
  1260 {
       
  1261   int i;
       
  1262   int j;
       
  1263   int acc;
       
  1264   int x;
       
  1265   int y, y_r, y_b, y_g;
       
  1266   uint16_t *dest = (uint16_t *) dest_u8;
       
  1267   uint16_t *src = (uint16_t *) src_u8;
       
  1268 
       
  1269   acc = *xacc;
       
  1270   for (i = 0; i < n; i++) {
       
  1271     j = acc >> 16;
       
  1272     x = acc & 0xffff >> 8;
       
  1273 
       
  1274     if (j - 1 >= 0 && j + 2 < src_width) {
       
  1275       y = vs_4tap_taps[x][0] * RGB555_R (src[MAX ((j - 1), 0)]);
       
  1276       y += vs_4tap_taps[x][1] * RGB555_R (src[j]);
       
  1277       y += vs_4tap_taps[x][2] * RGB555_R (src[(j + 1)]);
       
  1278       y += vs_4tap_taps[x][3] * RGB555_R (src[(j + 2)]);
       
  1279     } else {
       
  1280       y = vs_4tap_taps[x][0] * RGB555_R (src[CLAMP ((j - 1), 0,
       
  1281                   src_width - 1)]);
       
  1282       y += vs_4tap_taps[x][1] * RGB555_R (src[CLAMP (j, 0, src_width - 1)]);
       
  1283       y += vs_4tap_taps[x][2] * RGB555_R (src[CLAMP ((j + 1), 0,
       
  1284                   src_width - 1)]);
       
  1285       y += vs_4tap_taps[x][3] * RGB555_R (src[CLAMP ((j + 2), 0,
       
  1286                   src_width - 1)]);
       
  1287     }
       
  1288     y += (1 << (SHIFT - 1));
       
  1289     y_r = CLAMP (y >> SHIFT, 0, 255);
       
  1290 
       
  1291     if (j - 1 >= 0 && j + 2 < src_width) {
       
  1292       y = vs_4tap_taps[x][0] * RGB555_G (src[MAX ((j - 1), 0)]);
       
  1293       y += vs_4tap_taps[x][1] * RGB555_G (src[j]);
       
  1294       y += vs_4tap_taps[x][2] * RGB555_G (src[(j + 1)]);
       
  1295       y += vs_4tap_taps[x][3] * RGB555_G (src[(j + 2)]);
       
  1296     } else {
       
  1297       y = vs_4tap_taps[x][0] * RGB555_G (src[CLAMP ((j - 1), 0,
       
  1298                   src_width - 1)]);
       
  1299       y += vs_4tap_taps[x][1] * RGB555_G (src[CLAMP (j, 0, src_width - 1)]);
       
  1300       y += vs_4tap_taps[x][2] * RGB555_G (src[CLAMP ((j + 1), 0,
       
  1301                   src_width - 1)]);
       
  1302       y += vs_4tap_taps[x][3] * RGB555_G (src[CLAMP ((j + 2), 0,
       
  1303                   src_width - 1)]);
       
  1304     }
       
  1305     y += (1 << (SHIFT - 1));
       
  1306     y_g = CLAMP (y >> SHIFT, 0, 255);
       
  1307 
       
  1308     if (j - 1 >= 0 && j + 2 < src_width) {
       
  1309       y = vs_4tap_taps[x][0] * RGB555_B (src[MAX ((j - 1), 0)]);
       
  1310       y += vs_4tap_taps[x][1] * RGB555_B (src[j]);
       
  1311       y += vs_4tap_taps[x][2] * RGB555_B (src[(j + 1)]);
       
  1312       y += vs_4tap_taps[x][3] * RGB555_B (src[(j + 2)]);
       
  1313     } else {
       
  1314       y = vs_4tap_taps[x][0] * RGB555_B (src[CLAMP ((j - 1), 0,
       
  1315                   src_width - 1)]);
       
  1316       y += vs_4tap_taps[x][1] * RGB555_B (src[CLAMP (j, 0, src_width - 1)]);
       
  1317       y += vs_4tap_taps[x][2] * RGB555_B (src[CLAMP ((j + 1), 0,
       
  1318                   src_width - 1)]);
       
  1319       y += vs_4tap_taps[x][3] * RGB555_B (src[CLAMP ((j + 2), 0,
       
  1320                   src_width - 1)]);
       
  1321     }
       
  1322     y += (1 << (SHIFT - 1));
       
  1323     y_b = CLAMP (y >> SHIFT, 0, 255);
       
  1324 
       
  1325     dest[i] = RGB555 (y_r, y_b, y_g);
       
  1326     acc += increment;
       
  1327   }
       
  1328   *xacc = acc;
       
  1329 }
       
  1330 #ifdef __SYMBIAN32__
       
  1331 EXPORT_C
       
  1332 #endif
       
  1333 
       
  1334 
       
  1335 void
       
  1336 vs_scanline_merge_4tap_RGB555 (uint8_t * dest_u8, uint8_t * src1_u8,
       
  1337     uint8_t * src2_u8, uint8_t * src3_u8, uint8_t * src4_u8, int n, int acc)
       
  1338 {
       
  1339   int i;
       
  1340   int y, y_r, y_b, y_g;
       
  1341   int a, b, c, d;
       
  1342   uint16_t *dest = (uint16_t *) dest_u8;
       
  1343   uint16_t *src1 = (uint16_t *) src1_u8;
       
  1344   uint16_t *src2 = (uint16_t *) src2_u8;
       
  1345   uint16_t *src3 = (uint16_t *) src3_u8;
       
  1346   uint16_t *src4 = (uint16_t *) src4_u8;
       
  1347 
       
  1348   acc = (acc >> 8) & 0xff;
       
  1349   a = vs_4tap_taps[acc][0];
       
  1350   b = vs_4tap_taps[acc][1];
       
  1351   c = vs_4tap_taps[acc][2];
       
  1352   d = vs_4tap_taps[acc][3];
       
  1353 
       
  1354   for (i = 0; i < n; i++) {
       
  1355     y = a * RGB555_R (src1[i]);
       
  1356     y += b * RGB555_R (src2[i]);
       
  1357     y += c * RGB555_R (src3[i]);
       
  1358     y += d * RGB555_R (src4[i]);
       
  1359     y += (1 << (SHIFT - 1));
       
  1360     y_r = CLAMP (y >> SHIFT, 0, 255);
       
  1361 
       
  1362     y = a * RGB555_G (src1[i]);
       
  1363     y += b * RGB555_G (src2[i]);
       
  1364     y += c * RGB555_G (src3[i]);
       
  1365     y += d * RGB555_G (src4[i]);
       
  1366     y += (1 << (SHIFT - 1));
       
  1367     y_g = CLAMP (y >> SHIFT, 0, 255);
       
  1368 
       
  1369     y = a * RGB555_B (src1[i]);
       
  1370     y += b * RGB555_B (src2[i]);
       
  1371     y += c * RGB555_B (src3[i]);
       
  1372     y += d * RGB555_B (src4[i]);
       
  1373     y += (1 << (SHIFT - 1));
       
  1374     y_b = CLAMP (y >> SHIFT, 0, 255);
       
  1375 
       
  1376     dest[i] = RGB555 (y_r, y_b, y_g);
       
  1377   }
       
  1378 }
       
  1379 #ifdef __SYMBIAN32__
       
  1380 EXPORT_C
       
  1381 #endif
       
  1382 
       
  1383 
       
  1384 void
       
  1385 vs_image_scale_4tap_RGB555 (const VSImage * dest, const VSImage * src,
       
  1386     uint8_t * tmpbuf)
       
  1387 {
       
  1388   int yacc;
       
  1389   int y_increment;
       
  1390   int x_increment;
       
  1391   int i;
       
  1392   int j;
       
  1393   int xacc;
       
  1394   int k;
       
  1395 
       
  1396   if (dest->height == 1)
       
  1397     y_increment = 0;
       
  1398   else
       
  1399     y_increment = ((src->height - 1) << 16) / (dest->height - 1);
       
  1400 
       
  1401   if (dest->width == 1)
       
  1402     x_increment = 0;
       
  1403   else
       
  1404     x_increment = ((src->width - 1) << 16) / (dest->width - 1);
       
  1405 
       
  1406   k = 0;
       
  1407   for (i = 0; i < 4; i++) {
       
  1408     xacc = 0;
       
  1409     vs_scanline_resample_4tap_RGB555 (tmpbuf + i * dest->stride,
       
  1410         src->pixels + i * src->stride, dest->width, src->width,
       
  1411         &xacc, x_increment);
       
  1412   }
       
  1413 
       
  1414   yacc = 0;
       
  1415   for (i = 0; i < dest->height; i++) {
       
  1416     uint8_t *t0, *t1, *t2, *t3;
       
  1417 
       
  1418     j = yacc >> 16;
       
  1419 
       
  1420     while (j > k) {
       
  1421       k++;
       
  1422       if (k + 3 < src->height) {
       
  1423         xacc = 0;
       
  1424         vs_scanline_resample_4tap_RGB555 (tmpbuf + ((k + 3) & 3) * dest->stride,
       
  1425             src->pixels + (k + 3) * src->stride,
       
  1426             dest->width, src->width, &xacc, x_increment);
       
  1427       }
       
  1428     }
       
  1429 
       
  1430     t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride;
       
  1431     t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride;
       
  1432     t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride;
       
  1433     t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride;
       
  1434     vs_scanline_merge_4tap_RGB555 (dest->pixels + i * dest->stride,
       
  1435         t0, t1, t2, t3, dest->width, yacc & 0xffff);
       
  1436 
       
  1437     yacc += y_increment;
       
  1438   }
       
  1439 }