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

Symbian

开发平台:

Visual C++

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