565.c
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:32k
源码类别:

Symbian

开发平台:

Visual C++

  1. 1/* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: 565.c,v 1.2.8.1 2004/07/09 02:00:07 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include <stdlib.h>
  50. #include "nostatic/colorlib.h"
  51. #include "nostatic/yuv.h"
  52. /*
  53.  * Color conversion routines for converting YUV420 as produced by the
  54.  * RealVideo decoders to RGB565.
  55.  */
  56. /*
  57.  * Format-conversion routines.
  58.  * Use:
  59.  *  int XXXXtoYYYYEx (unsigned char *dest_ptr, int dest_width, int dest_height,
  60.  *      int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  61.  *      unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  62.  *      int src_x, int src_y, int src_dx, int src_dy);
  63.  * Input:
  64.  *  dest_ptr - pointer to a destination buffer
  65.  *  dest_width, dest_height - width/height of the destination image (pixels)
  66.  *  dest_pitch - pitch of the dest. buffer (in bytes; <0 - if bottom up image)
  67.  *  dest_x, dest_y, dest_dx, dest_dy - destination rectangle (pixels)
  68.  *  src_ptr - pointer to an input image
  69.  *  src_width, src_height - width/height of the input image (pixels)
  70.  *  src_pitch - pitch of the source buffer (in bytes; <0 - if bottom up image)
  71.  *  src_x, src_y, src_dx, src_dy - source rectangle (pixels)
  72.  * Returns:
  73.  *  0 - if success; -1 if failure.
  74.  * Notes:
  75.  *  a) In all cases, pointers to the source and destination buffers must be
  76.  *     DWORD aligned, and both pitch parameters must be multiple of 4!!!
  77.  *  b) Converters that deal with YUV 4:2:2, or 4:2:0 formats may also require
  78.  *     rectangle parameters (x,y,dx,dy) to be multiple of 2. Failure to provide
  79.  *     aligned rectangles will result in partially converted image.
  80.  *  c) Currently only scale factors of 1:1 and 2:1 are supported; if the rates
  81.  *     dest_dx/src_dx & dest_dy/src_dy are neither 1, or 2, the converters
  82.  *     will fail.
  83.  */
  84. #define BYTESPERPIXEL 2
  85. /* Indexing tables */
  86. static const int next[3] = {1, 2, 0};                 /* (ibuf+1)%3 table */
  87. static const int next2[3] = {2, 0, 1};                /* (ibuf+2)%3 table */
  88. /* Half resolution converter.  */
  89. static void halfI420toRGB565 (unsigned char *d1,
  90.       int dest_x, unsigned char *sy1, 
  91.       unsigned char *sy2, unsigned char *su, 
  92.       unsigned char *sv, int src_x, int dx, int isodd,
  93.       color_data_t* pcd)
  94. {
  95.   /* check if we have misaligned input/output: */
  96.   if ((src_x ^ dest_x) & 1) {
  97.     
  98.     ; /* not implemented yet */
  99.     
  100.   } else {
  101.     
  102.     /* aligned input/output: */
  103.     register int y11, y12;
  104.     register int rv1, guv1, bu1, rv2, guv2, bu2;
  105.     register int i;
  106.     
  107.     /* source width should always be multiples of 4 */
  108.     /*    assert((src_x & 3)==0); */
  109.     /* convert all integral 2x4 blocks: */
  110.     if (isodd)
  111.       for (i = 0; i < dx/4; i ++) {
  112. /* first 2x2 block */
  113. rv1 = pcd->rvtab[sv[0]];
  114. guv1 = pcd->gutab[su[0]] + pcd->gvtab[sv[0]];
  115. bu1 = pcd->butab[su[0]];
  116. y11 = (pcd->ytab[sy1[0]] + pcd->ytab[sy1[1]] + pcd->ytab[sy2[0]] + pcd->ytab[sy2[1]])>>2; /* avg */
  117. /* second 2x2 block */
  118. rv2  = pcd->rvtab[sv[1]];
  119. guv2 = pcd->gutab[su[1]] + pcd->gvtab[sv[1]];
  120. bu2  = pcd->butab[su[1]];
  121. y12 = (pcd->ytab[sy1[2]] + pcd->ytab[sy1[3]] + pcd->ytab[sy2[2]] + pcd->ytab[sy2[3]])>>2;
  122. /* output 4 bytes at a time */
  123. *(unsigned int *)(d1+0) =
  124.   (CLIP5[y11 + bu1  + DITH5L] << 0)  |
  125.   (CLIP6[y11 + guv1 + DITH6L] << 5)  |
  126.   (CLIP5[y11 + rv1  + DITH5L] << 11) |
  127.   (CLIP5[y12 + bu2  + DITH5H] << 16) |
  128.   (CLIP6[y12 + guv2 + DITH6H] << 21) |
  129.   (CLIP5[y12 + rv2  + DITH5H] << 27) ;
  130. /* next 4x2 block */
  131. sy1 += 4; sy2 += 4;
  132. su += 2; sv += 2;
  133. d1 += 2*BPP2;
  134.       }
  135.     else
  136.       for (i = 0; i < dx/4; i ++) {
  137. /* first 2x2 block */
  138. rv1 = pcd->rvtab[sv[0]];
  139. guv1 = pcd->gutab[su[0]] + pcd->gvtab[sv[0]];
  140. bu1 = pcd->butab[su[0]];
  141. y11 = (pcd->ytab[sy1[0]] + pcd->ytab[sy1[1]] + pcd->ytab[sy2[0]] + pcd->ytab[sy2[1]])>>2; /* avg */
  142. /* second 2x2 block */
  143. rv2  = pcd->rvtab[sv[1]];
  144. guv2 = pcd->gutab[su[1]] + pcd->gvtab[sv[1]];
  145. bu2  = pcd->butab[su[1]];
  146. y12 = (pcd->ytab[sy1[2]] + pcd->ytab[sy1[3]] + pcd->ytab[sy2[2]] + pcd->ytab[sy2[3]])>>2;
  147. /* output 4 bytes at a time */
  148. *(unsigned int *)(d1+0) =
  149.   (CLIP5[y11 + bu1  + DITH5H] << 0)  |
  150.   (CLIP6[y11 + guv1 + DITH6H] << 5)  |
  151.   (CLIP5[y11 + rv1  + DITH5H] << 11) |
  152.   (CLIP5[y12 + bu2  + DITH5L] << 16) |
  153.   (CLIP6[y12 + guv2 + DITH6L] << 21) |
  154.   (CLIP5[y12 + rv2  + DITH5L] << 27) ;
  155. /* next 4x2 block */
  156. sy1 += 4; sy2 += 4;
  157. su += 2; sv += 2;
  158. d1 += 2*BPP2;
  159.       }
  160.   }
  161. }
  162. static void dblineI420toRGB565 (unsigned char *d1, unsigned char *d2, 
  163. int dest_x, unsigned char *sy1, 
  164. unsigned char *sy2, unsigned char *su, 
  165. unsigned char *sv, int src_x, int dx,
  166. color_data_t* pcd)
  167. {
  168.     /* check if we have misaligned input/output: */
  169.     if ((src_x ^ dest_x) & 1) {
  170.         ; /* not implemented yet */
  171.     } else {
  172.         /* aligned input/output: */
  173.         register int y11, y12, y21, y22;
  174.         register int rv, guv, bu;
  175.         register int i;
  176.         /* convert first 2x1 block: */
  177.         if (dest_x & 1) {
  178.             rv  = pcd->rvtab[sv[0]];
  179.             guv = pcd->gutab[su[0]] + pcd->gvtab[sv[0]];
  180.             bu  = pcd->butab[su[0]];
  181.             y11 = pcd->ytab[sy1[0]];
  182.             y21 = pcd->ytab[sy2[0]];
  183.             /* output 2 bytes at a time */
  184.             *(unsigned short *)(d1+0) =
  185.                 (CLIP5[y11 + bu  + DITH5L] << 0)  |
  186.                 (CLIP6[y11 + guv + DITH6L] << 5)  |
  187.                 (CLIP5[y11 + rv  + DITH5L] << 11) ;
  188.             *(unsigned short *)(d2+0) =
  189.                 (CLIP5[y21 + bu  + DITH5H] << 0)  |
  190.                 (CLIP6[y21 + guv + DITH6H] << 5)  |
  191.                 (CLIP5[y21 + rv  + DITH5H] << 11) ;
  192.             sy1 += 1; sy2 += 1;
  193.             su += 1; sv += 1;
  194.             d1 += BPP2; d2 += BPP2;
  195.             dest_x ++; dx --;
  196.         }
  197.         /* convert first 2x2 block: */
  198.         if (dest_x & 2) {
  199.             rv  = pcd->rvtab[sv[0]];
  200.             guv = pcd->gutab[su[0]] + pcd->gvtab[sv[0]];
  201.             bu  = pcd->butab[su[0]];
  202.             y11 = pcd->ytab[sy1[0]];
  203.             y12 = pcd->ytab[sy1[1]];
  204.             /* output 4 bytes at a time */
  205.             *(unsigned int *)(d1+0) =
  206.                 (CLIP5[y11 + bu  + DITH5L] << 0)  |
  207.                 (CLIP6[y11 + guv + DITH6L] << 5)  |
  208.                 (CLIP5[y11 + rv  + DITH5L] << 11) |
  209.                 (CLIP5[y12 + bu  + DITH5H] << 16) |
  210.                 (CLIP6[y12 + guv + DITH6H] << 21) |
  211.                 (CLIP5[y12 + rv  + DITH5H] << 27) ;
  212.             y21 = pcd->ytab[sy2[0]];
  213.             y22 = pcd->ytab[sy2[1]];
  214.             *(unsigned int *)(d2+0) =
  215.                 (CLIP5[y21 + bu  + DITH5H] << 0)  |
  216.                 (CLIP6[y21 + guv + DITH6H] << 5)  |
  217.                 (CLIP5[y21 + rv  + DITH5H] << 11) |
  218.                 (CLIP5[y22 + bu  + DITH5L] << 16) |
  219.                 (CLIP6[y22 + guv + DITH6L] << 21) |
  220.                 (CLIP5[y22 + rv  + DITH5L] << 27) ;
  221.             sy1 += 2; sy2 += 2;
  222.             su += 1; sv += 1;
  223.             d1 += 2*BPP2; d2 += 2*BPP2;
  224.             dest_x += 2; dx -= 2;
  225.         }
  226.         /* convert all integral 2x4 blocks: */
  227.         for (i = 0; i < dx/4; i ++) {
  228.             /* first 2x2 block */
  229.             rv = pcd->rvtab[sv[0]];
  230.             guv = pcd->gutab[su[0]] + pcd->gvtab[sv[0]];
  231.             bu = pcd->butab[su[0]];
  232.             y11 = pcd->ytab[sy1[0]];
  233.             y12 = pcd->ytab[sy1[1]];
  234.             /* output 4 bytes at a time */
  235.             *(unsigned int *)(d1+0) =
  236.                 (CLIP5[y11 + bu  + DITH5L] << 0)  |
  237.                 (CLIP6[y11 + guv + DITH6L] << 5)  |
  238.                 (CLIP5[y11 + rv  + DITH5L] << 11) |
  239.                 (CLIP5[y12 + bu  + DITH5H] << 16) |
  240.                 (CLIP6[y12 + guv + DITH6H] << 21) |
  241.                 (CLIP5[y12 + rv  + DITH5H] << 27) ;
  242.             y21 = pcd->ytab[sy2[0]];
  243.             y22 = pcd->ytab[sy2[1]];
  244.             *(unsigned int *)(d2+0) =
  245.                 (CLIP5[y21 + bu  + DITH5H] << 0)  |
  246.                 (CLIP6[y21 + guv + DITH6H] << 5)  |
  247.                 (CLIP5[y21 + rv  + DITH5H] << 11) |
  248.                 (CLIP5[y22 + bu  + DITH5L] << 16) |
  249.                 (CLIP6[y22 + guv + DITH6L] << 21) |
  250.                 (CLIP5[y22 + rv  + DITH5L] << 27) ;
  251.             /* second 2x2 block */
  252.             rv  = pcd->rvtab[sv[1]];
  253.             guv = pcd->gutab[su[1]] + pcd->gvtab[sv[1]];
  254.             bu  = pcd->butab[su[1]];
  255.             y11 = pcd->ytab[sy1[2]];
  256.             y12 = pcd->ytab[sy1[3]];
  257.             *(unsigned int *)(d1+2*BPP2) =
  258.                 (CLIP5[y11 + bu  + DITH5L] << 0)  |
  259.                 (CLIP6[y11 + guv + DITH6L] << 5)  |
  260.                 (CLIP5[y11 + rv  + DITH5L] << 11) |
  261.                 (CLIP5[y12 + bu  + DITH5H] << 16) |
  262.                 (CLIP6[y12 + guv + DITH6H] << 21) |
  263.                 (CLIP5[y12 + rv  + DITH5H] << 27) ;
  264.             y21 = pcd->ytab[sy2[2]];
  265.             y22 = pcd->ytab[sy2[3]];
  266.             *(unsigned int *)(d2+2*BPP2) =
  267.                 (CLIP5[y21 + bu  + DITH5H] << 0)  |
  268.                 (CLIP6[y21 + guv + DITH6H] << 5)  |
  269.                 (CLIP5[y21 + rv  + DITH5H] << 11) |
  270.                 (CLIP5[y22 + bu  + DITH5L] << 16) |
  271.                 (CLIP6[y22 + guv + DITH6L] << 21) |
  272.                 (CLIP5[y22 + rv  + DITH5L] << 27) ;
  273.             /* next 4x2 block */
  274.             sy1 += 4; sy2 += 4;
  275.             su += 2; sv += 2;
  276.             d1 += 4*BPP2; d2 += 4*BPP2;
  277.         }
  278.         /* convert last 2x2 block: */
  279.         if (dx & 2) {
  280.             rv = pcd->rvtab[sv[0]];
  281.             guv = pcd->gutab[su[0]] + pcd->gvtab[sv[0]];
  282.             bu = pcd->butab[su[0]];
  283.             y11 = pcd->ytab[sy1[0]];
  284.             y12 = pcd->ytab[sy1[1]];
  285.             /* output 4 bytes at a time */
  286.             *(unsigned int *)(d1+0) =
  287.                 (CLIP5[y11 + bu  + DITH5L] << 0)  |
  288.                 (CLIP6[y11 + guv + DITH6L] << 5)  |
  289.                 (CLIP5[y11 + rv  + DITH5L] << 11) |
  290.                 (CLIP5[y12 + bu  + DITH5H] << 16) |
  291.                 (CLIP6[y12 + guv + DITH6H] << 21) |
  292.                 (CLIP5[y12 + rv  + DITH5H] << 27) ;
  293.             y21 = pcd->ytab[sy2[0]];
  294.             y22 = pcd->ytab[sy2[1]];
  295.             *(unsigned int *)(d2+0) =
  296.                 (CLIP5[y21 + bu  + DITH5H] << 0)  |
  297.                 (CLIP6[y21 + guv + DITH6H] << 5)  |
  298.                 (CLIP5[y21 + rv  + DITH5H] << 11) |
  299.                 (CLIP5[y22 + bu  + DITH5L] << 16) |
  300.                 (CLIP6[y22 + guv + DITH6L] << 21) |
  301.                 (CLIP5[y22 + rv  + DITH5L] << 27) ;
  302.             sy1 += 2; sy2 += 2;
  303.             su += 1; sv += 1;
  304.             d1 += 2*BPP2; d2 += 2*BPP2;
  305.             dx -= 2;
  306.         }
  307.         /* convert last 2x1 block: */
  308.         if (dx & 1) {
  309.             rv  = pcd->rvtab[sv[0]];
  310.             guv = pcd->gutab[su[0]] + pcd->gvtab[sv[0]];
  311.             bu  = pcd->butab[su[0]];
  312.             y11 = pcd->ytab[sy1[0]];
  313.             y21 = pcd->ytab[sy2[0]];
  314.             /* output 2 bytes at a time */
  315.             *(unsigned short *)(d1+0) =
  316.                 (CLIP5[y11 + bu  + DITH5L] << 0)  |
  317.                 (CLIP6[y11 + guv + DITH6L] << 5)  |
  318.                 (CLIP5[y11 + rv  + DITH5L] << 11) ;
  319.             *(unsigned short *)(d2+0) =
  320.                 (CLIP5[y21 + bu  + DITH5H] << 0)  |
  321.                 (CLIP6[y21 + guv + DITH6H] << 5)  |
  322.                 (CLIP5[y21 + rv  + DITH5H] << 11) ;
  323.         }
  324.     }
  325. }
  326. #define DITH1X4L 0x01002004
  327. #define DITH1X4H 0x0300600C
  328. #define DITH2X4L 0x02004008
  329. #define DITH2X4H 0x0600C018
  330. #define DITH4X4L 0x04008010
  331. #define DITH4X4H 0x0C018030
  332. /* RGB565 version: */
  333. static void dblineXRGBtoRGB565x2 (unsigned char *d1, unsigned char *d2, int dest_x,
  334.   unsigned char *s1, unsigned char *s2, int src_x, int dx,
  335.   color_data_t* pcd)
  336. {
  337.     register unsigned int a, b, c, d, e, f;
  338.     register unsigned int w, x, y, z;
  339.     /* convert first 2x1 block: */
  340.     if (dest_x & 1) {
  341.         /* Input pels  =>   Output pels
  342.          *  a b             w  x
  343.          *  c d             w' x'
  344.          */
  345.         /* top line */
  346.         a = *(unsigned int *)s1;
  347.         b = *(unsigned int *)(s1+BPP4);
  348.         w = a     + DITH1X4L;
  349.         x = a + b + DITH2X4H;
  350.         /* pack and store */
  351.         *(unsigned int *)d1 =
  352.             ((w & 0x000000f8) >> 3)  |
  353.             ((w & 0x0007e000) >> 8)  |
  354.             ((w & 0x3e000000) >> 14) |
  355.             ((x & 0x000001f0) << 12) |
  356.             ((x & 0x000fc000) << 7)  |
  357.             ((x & 0x7c000000) << 1);
  358.         /* bottom line */
  359.         c = *(unsigned int *)s2;
  360.         d = *(unsigned int *)(s2+BPP4);
  361.         w = a + c         + DITH2X4H;
  362.         x = a + b + c + d + DITH4X4L;
  363.         /* pack and store */
  364.         *(unsigned int *)d2 =
  365.             ((w & 0x000001f0) >> 4)  |
  366.             ((w & 0x000fc000) >> 9)  |
  367.             ((w & 0x7c000000) >> 15) |
  368.             ((x & 0x000003e0) << 11) |
  369.             ((x & 0x001f8000) << 6)  |
  370.             ((x & 0xf8000000) << 0);
  371.         /* bump pointers to next block */
  372.         s1 += BPP4; s2 += BPP4;
  373.         d1 += 2*BPP2; d2 += 2*BPP2;
  374.         dx -= 1;
  375.     }
  376.     /* process all integral 2x2 blocks: */
  377.     while (dx > 2) {    /* we need to leave at least one block */
  378.         /*
  379.          * Input stored as 00 RRRRRRRR 000 GGGGGGGG 000 BBBBBBBB
  380.          *
  381.          * Input pels       Output pels
  382.          *  a b e           w  x  y  z
  383.          *  c d f           w' x' y' z'
  384.          */
  385.         /* top line */
  386.         a = *(unsigned int *)s1;
  387.         b = *(unsigned int *)(s1+BPP4);
  388.         e = *(unsigned int *)(s1+2*BPP4);
  389.         w = a     + DITH1X4L;
  390.         x = a + b + DITH2X4H;
  391.         y = b     + DITH1X4L;
  392.         z = b + e + DITH2X4H;
  393.         /* pack and store */
  394.         *(unsigned int *)d1 =
  395.             ((w & 0x000000f8) >> 3)  |
  396.             ((w & 0x0007e000) >> 8)  |
  397.             ((w & 0x3e000000) >> 14) |
  398.             ((x & 0x000001f0) << 12) |
  399.             ((x & 0x000fc000) << 7)  |
  400.             ((x & 0x7c000000) << 1);
  401.         *(unsigned int *)(d1+2*BPP2) =
  402.             ((y & 0x000000f8) >> 3)  |
  403.             ((y & 0x0007e000) >> 8)  |
  404.             ((y & 0x3e000000) >> 14) |
  405.             ((z & 0x000001f0) << 12) |
  406.             ((z & 0x000fc000) << 7)  |
  407.             ((z & 0x7c000000) << 1);
  408.         /* bottom line */
  409.         c = *(unsigned int *)s2;
  410.         d = *(unsigned int *)(s2+BPP4);
  411.         f = *(unsigned int *)(s2+2*BPP4);
  412.         w = a + c         + DITH2X4H;
  413.         x = a + b + c + d + DITH4X4L;
  414.         y = b + d         + DITH2X4H;
  415.         z = b + e + d + f + DITH4X4L;
  416.         /* pack and store */
  417.         *(unsigned int *)d2 =
  418.             ((w & 0x000001f0) >> 4)  |
  419.             ((w & 0x000fc000) >> 9)  |
  420.             ((w & 0x7c000000) >> 15) |
  421.             ((x & 0x000003e0) << 11) |
  422.             ((x & 0x001f8000) << 6)  |
  423.             ((x & 0xf8000000) << 0);
  424.         *(unsigned int *)(d2+2*BPP2) =
  425.             ((y & 0x000001f0) >> 4)  |
  426.             ((y & 0x000fc000) >> 9)  |
  427.             ((y & 0x7c000000) >> 15) |
  428.             ((z & 0x000003e0) << 11) |
  429.             ((z & 0x001f8000) << 6)  |
  430.             ((z & 0xf8000000) << 0);
  431.         /* next 2x2 input block */
  432.         s1 += 2*BPP4; s2 += 2*BPP4;
  433.         d1 += 4*BPP2; d2 += 4*BPP2;
  434.         dx -= 2;
  435.     }
  436.     /* check if this is the last 2x2 block: */
  437.     if (dx > 1) {
  438.         /*
  439.          * For last 4 output pels, repeat final input pel
  440.          * for offscreen input.  Equivalent to pixel-doubling the
  441.          * last output pel.
  442.          */
  443.         /* top line */
  444.         a = *(unsigned int *)s1;
  445.         b = *(unsigned int *)(s1+BPP4);
  446.         e = b;      /* repeat last input pel */
  447.         w = a     + DITH1X4L;
  448.         x = a + b + DITH2X4H;
  449.         y = b     + DITH1X4L;
  450.         z = b + e + DITH2X4H;
  451.         /* pack and store */
  452.         *(unsigned int *)d1 =
  453.             ((w & 0x000000f8) >> 3)  |
  454.             ((w & 0x0007e000) >> 8)  |
  455.             ((w & 0x3e000000) >> 14) |
  456.             ((x & 0x000001f0) << 12) |
  457.             ((x & 0x000fc000) << 7)  |
  458.             ((x & 0x7c000000) << 1);
  459.         *(unsigned int *)(d1+2*BPP2) =
  460.             ((y & 0x000000f8) >> 3)  |
  461.             ((y & 0x0007e000) >> 8)  |
  462.             ((y & 0x3e000000) >> 14) |
  463.             ((z & 0x000001f0) << 12) |
  464.             ((z & 0x000fc000) << 7)  |
  465.             ((z & 0x7c000000) << 1);
  466.         /* bottom line */
  467.         c = *(unsigned int *)s2;
  468.         d = *(unsigned int *)(s2+BPP4);
  469.         f = d;      /* repeat last input pel */
  470.         w = a + c         + DITH2X4H;
  471.         x = a + b + c + d + DITH4X4L;
  472.         y = b + d         + DITH2X4H;
  473.         z = b + e + d + f + DITH4X4L;
  474.         /* pack and store */
  475.         *(unsigned int *)d2 =
  476.             ((w & 0x000001f0) >> 4)  |
  477.             ((w & 0x000fc000) >> 9)  |
  478.             ((w & 0x7c000000) >> 15) |
  479.             ((x & 0x000003e0) << 11) |
  480.             ((x & 0x001f8000) << 6)  |
  481.             ((x & 0xf8000000) << 0);
  482.         *(unsigned int *)(d2+2*BPP2) =
  483.             ((y & 0x000001f0) >> 4)  |
  484.             ((y & 0x000fc000) >> 9)  |
  485.             ((y & 0x7c000000) >> 15) |
  486.             ((z & 0x000003e0) << 11) |
  487.             ((z & 0x001f8000) << 6)  |
  488.             ((z & 0xf8000000) << 0);
  489.     } else {
  490.         /* last 2x1 block: */
  491.         /* Input pels  =>   Output pels
  492.          *  a b             w  x
  493.          *  c d             w' x'
  494.          */
  495.         /* top line */
  496.         a = *(unsigned int *)s1;
  497.         b = a;      /* repeat last input pel */
  498.         w = a     + DITH1X4L;
  499.         x = a + b + DITH2X4H;
  500.         /* pack and store */
  501.         *(unsigned int *)d1 =
  502.             ((w & 0x000000f8) >> 3)  |
  503.             ((w & 0x0007e000) >> 8)  |
  504.             ((w & 0x3e000000) >> 14) |
  505.             ((x & 0x000001f0) << 12) |
  506.             ((x & 0x000fc000) << 7)  |
  507.             ((x & 0x7c000000) << 1);
  508.         /* bottom line */
  509.         c = *(unsigned int *)s2;
  510.         d = c;      /* repeat last input pel */
  511.         w = a + c         + DITH2X4H;
  512.         x = a + b + c + d + DITH4X4L;
  513.         /* pack and store */
  514.         *(unsigned int *)d2 =
  515.             ((w & 0x000001f0) >> 4)  |
  516.             ((w & 0x000fc000) >> 9)  |
  517.             ((w & 0x7c000000) >> 15) |
  518.             ((x & 0x000003e0) << 11) |
  519.             ((x & 0x001f8000) << 6)  |
  520.             ((x & 0xf8000000) << 0);
  521.     }
  522. }
  523. /*
  524.  * Convert two YUV lines into RGB linebufs.
  525.  * Produces two RGB lines per call.
  526.  * Output in padded RGB format, needed for SIMD interpolation.
  527.  */
  528. static void dblineI420toXRGB (unsigned char *d1, unsigned char *d2, int dest_x,
  529.     unsigned char *sy1, unsigned char *sy2, unsigned char *su, unsigned char *sv,
  530.       int src_x, int dx,
  531.       color_data_t* pcd)
  532. {
  533.     register int y1, y2, rv, guv, bu;
  534.     register int i;
  535.     /* convert first 2x1 block: */
  536.     if (src_x & 1) {
  537.         bu = pcd->butab[su[0]];
  538.         guv = pcd->gutab[su[0]] + pcd->gvtab[sv[0]];
  539.         rv = pcd->rvtab[sv[0]];
  540.         y1 = pcd->ytab[sy1[0]];
  541.         y2 = pcd->ytab[sy2[0]];
  542.         /* first line 00rrrrrr.rr000ggg.ggggg000.bbbbbbbb: */
  543.         *(unsigned int *)(d1+0) =
  544.             (CLIP8[y1 + bu])        |
  545.             (CLIP8[y1 + guv] << 11) |
  546.             (CLIP8[y1 + rv]  << 22) ;
  547.         /* second line 00rrrrrr.rr000ggg.ggggg000.bbbbbbbb: */
  548.         *(unsigned int *)(d2+0) =
  549.             (CLIP8[y2 + bu])        |
  550.             (CLIP8[y2 + guv] << 11) |
  551.             (CLIP8[y2 + rv]  << 22) ;
  552.         sy1 += 1; sy2 += 1;
  553.         su += 1; sv += 1;
  554.         d1 += BPP4; d2 += BPP4;
  555.         dx --;
  556.     }
  557.     /* convert all integral 2x2 blocks: */
  558.     for (i = 0; i < dx/2; i ++) {
  559.         bu = pcd->butab[su[0]];
  560.         guv = pcd->gutab[su[0]] + pcd->gvtab[sv[0]];
  561.         rv = pcd->rvtab[sv[0]];
  562.         y1 = pcd->ytab[sy1[0]];
  563.         y2 = pcd->ytab[sy2[0]];
  564.         /* first line 00rrrrrr.rr000ggg.ggggg000.bbbbbbbb: */
  565.         *(unsigned int *)(d1+0) =
  566.             (CLIP8[y1 + bu])        |
  567.             (CLIP8[y1 + guv] << 11) |
  568.             (CLIP8[y1 + rv]  << 22) ;
  569.         /* second line 00rrrrrr.rr000ggg.ggggg000.bbbbbbbb: */
  570.         *(unsigned int *)(d2+0) =
  571.             (CLIP8[y2 + bu])        |
  572.             (CLIP8[y2 + guv] << 11) |
  573.             (CLIP8[y2 + rv]  << 22) ;
  574.         /* 2nd row: */
  575.         y1 = pcd->ytab[sy1[1]];
  576.         y2 = pcd->ytab[sy2[1]];
  577.         /* first line 00rrrrrr.rr000ggg.ggggg000.bbbbbbbb: */
  578.         *(unsigned int *)(d1+BPP4) =
  579.             (CLIP8[y1 + bu])        |
  580.             (CLIP8[y1 + guv] << 11) |
  581.             (CLIP8[y1 + rv]  << 22) ;
  582.         /* second line 00rrrrrr.rr000ggg.ggggg000.bbbbbbbb: */
  583.         *(unsigned int *)(d2+BPP4) =
  584.             (CLIP8[y2 + bu])        |
  585.             (CLIP8[y2 + guv] << 11) |
  586.             (CLIP8[y2 + rv]  << 22) ;
  587.         /* next 2x2 block */
  588.         sy1 += 2; sy2 += 2;
  589.         su += 1; sv += 1;
  590.         d1 += 2*BPP4; d2 += 2*BPP4;
  591.     }
  592.     /* convert last 2x1 block: */
  593.     if (dx & 1) {
  594.         bu = pcd->butab[su[0]];
  595.         guv = pcd->gutab[su[0]] + pcd->gvtab[sv[0]];
  596.         rv = pcd->rvtab[sv[0]];
  597.         y1 = pcd->ytab[sy1[0]];
  598.         y2 = pcd->ytab[sy2[0]];
  599.         /* first line 00rrrrrr.rr000ggg.ggggg000.bbbbbbbb: */
  600.         *(unsigned int *)(d1+0) =
  601.             (CLIP8[y1 + bu])        |
  602.             (CLIP8[y1 + guv] << 11) |
  603.             (CLIP8[y1 + rv]  << 22) ;
  604.         /* second line BGR0 */
  605.         *(unsigned int *)(d2+0) =
  606.             (CLIP8[y2 + bu])        |
  607.             (CLIP8[y2 + guv] << 11) |
  608.             (CLIP8[y2 + rv]  << 22) ;
  609.     }
  610. }
  611. /*
  612.  * I420->RGB565 converter:
  613.  */
  614. int I420toRGB565 (unsigned char *dest_ptr, int dest_width, int dest_height,
  615.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  616.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  617.     int src_x, int src_y, int src_dx, int src_dy,
  618.   color_data_t* pcd)
  619. {
  620.     /* scale factors: */
  621.     int scale_x, scale_y;
  622.     /* check arguments: */
  623.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  624.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  625.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  626.         return -1;
  627.     /* check if bottop-up images: */
  628.     if (dest_pitch < 0) dest_ptr -= (dest_height-1) * dest_pitch;
  629.     if (src_pitch <= 0) return -1;          /* not supported */
  630.     /* check if 1:1 scale: */
  631.     if (scale_x == 1 && scale_y == 1) {
  632.         /* color converter to use: */
  633.         void (*dbline) (unsigned char *d1, unsigned char *d2, int dest_x,
  634.             unsigned char *sy1, unsigned char *sy2, unsigned char *su, unsigned char *sv,
  635.             int src_x, int dx, color_data_t* pcd) = 
  636.             dblineI420toRGB565;
  637.         /* local variables: */
  638.         unsigned char *sy1, *sy2, *su, *sv, *d1, *d2;
  639.         register int j;
  640.         /* get pointers: */
  641.         sy1 = src_ptr + (src_x + src_y * src_pitch);        /* luma offset */
  642.         sy2 = sy1 + src_pitch;
  643.         su  = src_ptr + src_height * src_pitch + (src_x/2 + src_y/2 * src_pitch);
  644.         sv  = su + src_height * src_pitch / 4;
  645.         d1  = dest_ptr + dest_x * 2 + dest_y * dest_pitch; /* RGB offset */
  646.         d2  = d1 + dest_pitch;
  647.         /* convert a top line: */
  648.         if (src_y & 1) {                        /* chroma shift */
  649.             /* this is a bit inefficient, but who cares??? */
  650.             (* dbline) (d1, d1, dest_x, sy1, sy1, su, sv, src_x, src_dx, pcd);
  651.             sy1 += src_pitch;   sy2 += src_pitch;
  652.             su  += src_pitch/2; sv  += src_pitch/2;
  653.             d1  += dest_pitch;  d2  += dest_pitch;
  654.             dest_dy --;
  655.         }
  656.         /* convert aligned portion of the image: */
  657.         for (j = 0; j < dest_dy/2; j ++) {
  658.             /* convert two lines a time: */
  659.             (* dbline) (d1, d2, dest_x, sy1, sy2, su, sv, src_x, src_dx, pcd);
  660.             sy1 += src_pitch*2; sy2 += src_pitch*2;
  661.             su  += src_pitch/2; sv  += src_pitch/2;
  662.             d1  += dest_pitch*2; d2 += dest_pitch*2;
  663.         }
  664.         /* convert bottom line (if dest_dy is odd): */
  665.         if (dest_dy & 1) {
  666.             /* convert one line only: */
  667.             (* dbline) (d1, d1, dest_x, sy1, sy1, su, sv, src_x, src_dx, pcd);
  668.         }
  669.         return 0;
  670.     }
  671.     /* check if 2:1 scale: */
  672.     if (scale_x == 2 && scale_y == 2) {
  673.         /* color converter & interpolator to use: */
  674.         void (*cvt) (unsigned char *d1, unsigned char *d2, int dest_x,
  675.             unsigned char *sy1, unsigned char *sy2, unsigned char *su, unsigned char *sv,
  676.             int src_x, int dx, color_data_t* pcd) = dblineI420toXRGB;
  677.         void (*x2) (unsigned char *d1, unsigned char *d2, int dest_x,
  678.             unsigned char *s1, unsigned char *s2, int src_x, int dx, color_data_t* pcd) = dblineXRGBtoRGB565x2;
  679.         /* local variables: */
  680.         unsigned char *sy1, *sy2, *su, *sv, *d1, *d2;
  681.         register int dy = src_dy;
  682.         /* line buffers (we want them to be as compact as possible): */
  683.         int ibuf = 0;                           /* circular buffer index */
  684.         unsigned char * buf[3];                 /* actual pointers  */
  685.         buf[0] = pcd->linebuf;
  686.         buf[1] = pcd->linebuf + src_dx * BPP4;
  687.         buf[2] = pcd->linebuf + 2 * src_dx * BPP4;
  688.         /* get pointers: */
  689.         sy1 = src_ptr + (src_x + src_y * src_pitch);        /* luma offset */
  690.         sy2 = sy1 + src_pitch;
  691.         su  = src_ptr + src_height * src_pitch + (src_x/2 + src_y/2 * src_pitch);
  692.         sv  = su + src_height * src_pitch / 4;
  693.         d1  = dest_ptr + dest_x * BYTESPERPIXEL + dest_y * dest_pitch; /* RGB offset */
  694.         d2  = d1 + dest_pitch;
  695.         /* check if we have misaligned top line: */
  696.         if (src_y & 1) {
  697.             /* convert an odd first line: */
  698.             (*cvt) (buf[ibuf], buf[ibuf], 0, sy1, sy1, su, sv, src_x, src_dx, pcd);
  699.             sy1 += src_pitch;   sy2 += src_pitch;
  700.             su  += src_pitch/2; sv  += src_pitch/2;
  701.             dy --;
  702.         } else {
  703.             /* otherwise, convert first two lines: */
  704.             (*cvt) (buf[next[ibuf]], buf[next2[ibuf]], 0, sy1, sy2, su, sv, src_x, src_dx, pcd);
  705.             sy1 += src_pitch*2; sy2 += src_pitch*2;
  706.             su  += src_pitch/2; sv  += src_pitch/2;
  707.             ibuf = next[ibuf];      /* skip first interpolation: */
  708.             (*x2) (d1, d2, dest_x, buf[ibuf], buf[next[ibuf]], 0, src_dx, pcd);
  709.             d1  += dest_pitch*2; d2  += dest_pitch*2;
  710.             ibuf = next[ibuf];
  711.             dy -= 2;
  712.         }
  713.         /*
  714.          * Convert & interpolate the main portion of image:
  715.          *
  716.          *  source:      temp.store:                destination:
  717.          *
  718.          *               buf[ibuf] -------    /--> d1
  719.          *                                  x2  --> d2
  720.          *  s1 --   /-> buf[next[ibuf]] -<    /--> d1'=d1+2*pitch
  721.          *        cvt                       x2 ---> d2'=d2+2*pitch
  722.          *  s2 --/   -> buf[next2[ibuf]] /
  723.          */
  724.         while (dy >= 2) {
  725.             /* convert two lines into XRGB buffers: */
  726.             (*cvt) (buf[next[ibuf]], buf[next2[ibuf]], 0, sy1, sy2, su, sv, src_x, src_dx, pcd);
  727.             sy1 += src_pitch*2; sy2 += src_pitch*2;
  728.             su  += src_pitch/2; sv  += src_pitch/2;
  729.             /* interpolate first line: */
  730.             (*x2) (d1, d2, dest_x, buf[ibuf], buf[next[ibuf]], 0, src_dx, pcd);
  731.             d1  += dest_pitch*2; d2  += dest_pitch*2;
  732.             ibuf = next[ibuf];
  733.             /* interpolate second one: */
  734.             (*x2) (d1, d2, dest_x, buf[ibuf], buf[next[ibuf]], 0, src_dx, pcd);
  735.             d1  += dest_pitch*2; d2  += dest_pitch*2;
  736.             ibuf = next[ibuf];
  737.             dy -= 2;
  738.         }
  739.         /* check the # of remaining rows: */
  740.         if (dy & 1) {
  741.             /* convert the last odd line: */
  742.             (*cvt) (buf[next[ibuf]], buf[next[ibuf]], 0, sy1, sy1, su, sv, src_x, src_dx, pcd);
  743.             /* interpolate first line: */
  744.             (*x2) (d1, d2, dest_x, buf[ibuf], buf[next[ibuf]], 0, src_dx, pcd);
  745.             d1  += dest_pitch*2; d2  += dest_pitch*2;
  746.             ibuf = next[ibuf];
  747.             /* replicate the last line: */
  748.             (*x2) (d1, d2, dest_x, buf[ibuf], buf[ibuf], 0, src_dx, pcd);
  749.         } else {
  750.             /* replicate the last line: */
  751.             (*x2) (d1, d2, dest_x, buf[ibuf], buf[ibuf], 0, src_dx, pcd);
  752.         }
  753.         return 0;
  754.     }
  755.     /* check for 1/2 X scaling */
  756.     if (scale_x == 0 && scale_y == 0) {
  757.         /* local variables: */
  758.         unsigned char *sy1, *sy2, *su, *sv, *d1, *d2;
  759.         register int j;
  760.         /* get pointers: */
  761.         sy1 = src_ptr + (src_x + src_y * src_pitch);        /* luma offset */
  762.         sy2 = sy1 + src_pitch;
  763.         su  = src_ptr + src_height * src_pitch + (src_x/2 + src_y/2 * src_pitch);
  764.         sv  = su + src_height * src_pitch / 4;
  765.         d1  = dest_ptr + dest_x * 2 + dest_y * dest_pitch; /* RGB offset */
  766.         d2  = d1 + dest_pitch;
  767.         /* convert aligned portion of the image: */
  768.         for (j = 0; j < dest_dy>>1; j ++) {
  769.             /* convert two lines a time: */
  770.             halfI420toRGB565 (d1, dest_x, sy1, sy2, su, sv, src_x, src_dx, 0, pcd);
  771.             sy1 += src_pitch*2; sy2 += src_pitch*2;
  772.             su  += src_pitch/2; sv  += src_pitch/2;
  773.             d1  += dest_pitch;
  774.             halfI420toRGB565 (d1, dest_x, sy1, sy2, su, sv, src_x, src_dx, 1, pcd);
  775.             sy1 += src_pitch*2; sy2 += src_pitch*2;
  776.             su  += src_pitch/2; sv  += src_pitch/2;
  777.             d1  += dest_pitch;
  778.         }
  779.         return 0;
  780.     }
  781.     /* conversion is not supported */
  782.     return -1;
  783. }
  784. /*
  785.  * InitI420toRGB565 initializes the minimum set of clip tables necessary to perform
  786.  * color conversion to 16 bit RGB.  The 8-bit clip table is necessary for 2x
  787.  * interpolation.
  788.  *
  789.  * This routine also calls SetSrcI420Colors, which initializes color conversion tables
  790.  * and adds color balance.
  791.  */
  792. void InitI420toRGB565(float brightness, float contrast, float saturation, float hue,
  793.       color_data_t* pcd)
  794. {
  795.     InitColorData(pcd);
  796.     SetSrcI420Colors (brightness, contrast, saturation, hue, pcd);
  797. }
  798. void UninitI420toRGB565( ){
  799.     /* noop */
  800. }