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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: rgb2yuv.c,v 1.2.48.1 2004/07/09 02:00:18 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. /*** #includes: ********************************************/
  50. #include "env.h"
  51. #include "rgb.h"    /* basic RGB-data definitions & macros */
  52. #include "yuv.h"    /* YUV-to-RGB conversion tables & macros */
  53. #include "clip.h"   /* macros for clipping & dithering */
  54. #include "scale.h"  /* scale algorithms */
  55. #include "colorlib.h"
  56. /*** RGB to YUV color converters: **************************/
  57. /*
  58.  * These functions were borrowed from our "old" color conversion library,
  59.  * and they do not support things like stretching or color adjustments.
  60.  * Given some more time this module should be completely rewritten.
  61.  *
  62.  ***************/
  63. /*-----------------2/24/2002 7:45AM-----------------
  64.  * Replaced the old code with macros.
  65.  * In-place resizing and color adjustments are not added since nobody
  66.  * really asked for it, and it would have blown the code by factor of 6 (at least).
  67.  * Yuriy.
  68.  * --------------------------------------------------*/
  69. /*-----------------9/19/2002 2:06PM-----------------
  70.  * Added support for byte-swapped RGB32 (BGR_32) and BGR24 input formats.
  71.  * To avoid changes (table reordering) in other modules, the definitions
  72.  * related to these formats are placed here, instead of "rgb.h".
  73.  * Yuriy.
  74.  * --------------------------------------------------*/
  75. /* new RGB format IDs: */
  76. #define BGR_32_ID           RGB_FORMATS
  77. #define BGR24_ID            (RGB_FORMATS + 1)
  78. /* bytes per pixel: */
  79. #define BGR_32_BPP          4
  80. #define BGR24_BPP           3
  81. /* local pixel representations: */
  82. #define BGR_32_PIXEL(a)     RGBX_PIXEL(a)
  83. #define BGR24_PIXEL(a)      RGB24_PIXEL(a)
  84. /* load/store/copy pixel macros: */
  85. #define BGR_32_LOAD(s,a)    RGBX_LOAD(s,a,unsigned int)
  86. #define BGR_32_STORE(d,a)   RGBX_STORE(d,a,unsigned int)
  87. #define BGR_32_COPY(da,sa)  RGBX_COPY(da,sa)
  88. #define BGR24_LOAD(s,a)     a##_r=(s)[0], a##_g=(s)[1], a##_b=(s)[2]
  89. #define BGR24_STORE(d,a)    (d)[0]=a##_r, (d)[1]=a##_g, (d)[2]=a##_b
  90. #define BGR24_COPY(da,sa)   da##_r=sa##_r, da##_g=sa##_g, da##_b=sa##_b
  91. /* BGR_32 bit fields: 0xBBGGRR00: */
  92. #define BGR_32_R_START      8
  93. #define BGR_32_R_BITS       8
  94. #define BGR_32_G_START      16
  95. #define BGR_32_G_BITS       8
  96. #define BGR_32_B_START      24
  97. #define BGR_32_B_BITS       8
  98. /* fields extraction/assignment macros: */
  99. #define BGR_32_GET_R(a)     RGBX_GET_X(BGR_32,R,a)
  100. #define BGR_32_GET_G(a)     RGBX_GET_X(BGR_32,G,a)
  101. #define BGR_32_GET_B(a)     RGBX_GET_X(BGR_32,B,a)
  102. #define BGR_32_SET(a,r,g,b) RGBX_SET(  BGR_32,a,r,g,b)
  103. #define BGR24_GET_R(a)      (a##_r)
  104. #define BGR24_GET_G(a)      (a##_g)
  105. #define BGR24_GET_B(a)      (a##_b)
  106. #define BGR24_SET(a,r,g,b)  a##_b=(b), a##_g=(g), a##_r=(r)
  107. /***************************************************************/
  108. /*
  109.  * YUV 4:2:0 chroma resampling modes:
  110.  * Input chroma     a b
  111.  *  samples:        c d
  112.  *
  113.  * CRM_11_11:       (a+b+c+d) / 4
  114.  * CRM_11_00:       (a+b) / 2
  115.  * CRM_00_11:       (c+d) / 2
  116.  */
  117. #define CHROMA_RESAMPLING_MODES     3
  118. /*
  119.  * 2x2-block load-convert-store macros:
  120.  */
  121. /* CRM_11_11 (both lines) chroma resampling: */
  122. #define CONVERT_2x2_CHROMA_11_11(dy1,dy2,du,dv,sf,s1,s2)            
  123.     {                                                               
  124.         /* local variables: */                                      
  125.         PIXEL(sf,x);                                                
  126.         register unsigned int r, b, y;                              
  127.         register unsigned int r4, b4, y4;   /* combined quant-s */  
  128.                                                                     
  129.         /* process lumas: */                                        
  130.         LOAD(sf,s1,x);              /* [0,0] */                     
  131.         r4 = (r = GET_R(sf,x));                                     
  132.         b4 = (b = GET_B(sf,x));                                     
  133.         y4 = (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);     
  134.         dy1[0] = yytab [y];                                         
  135.                                                                     
  136.         LOAD(sf,s1+BPP(sf),x);      /* [0,1] */                     
  137.         r4 += (r = GET_R(sf,x));                                    
  138.         b4 += (b = GET_B(sf,x));                                    
  139.         y4 += (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);    
  140.         dy1[1] = yytab [y];                                         
  141.                                                                     
  142.         LOAD(sf,s2,x);              /* [1,0] */                     
  143.         r4 += (r = GET_R(sf,x));                                    
  144.         b4 += (b = GET_B(sf,x));                                    
  145.         y4 += (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);    
  146.         dy2[0] = yytab [y];                                         
  147.                                                                     
  148.         LOAD(sf,s2+BPP(sf),x);      /* [1,1] */                     
  149.         r4 += (r = GET_R(sf,x));                                    
  150.         b4 += (b = GET_B(sf,x));                                    
  151.         y4 += (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);    
  152.         dy2[1] = yytab [y];                                         
  153.                                                                     
  154.         /* average chromas: */                                      
  155.         dv[0] = vrytab [VMIN+(r4-y4)/4];                            
  156.         du[0] = ubytab [UMIN+(b4-y4)/4];                            
  157.     }
  158. /* CRM_11_00 (upper line) chroma resampling: */
  159. #define CONVERT_2x2_CHROMA_11_00(dy1,dy2,du,dv,sf,s1,s2)            
  160.     {                                                               
  161.         /* local variables: */                                      
  162.         PIXEL(sf,x);                                                
  163.         register unsigned int r, b, y;                              
  164.         register unsigned int r2, b2, y2;   /* 1st line combined */ 
  165.                                                                     
  166.         /* process lumas: */                                        
  167.         LOAD(sf,s1,x);              /* [0,0] */                     
  168.         r2 = (r = GET_R(sf,x));                                     
  169.         b2 = (b = GET_B(sf,x));                                     
  170.         y2 = (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);     
  171.         dy1[0] = yytab [y];                                         
  172.                                                                     
  173.         LOAD(sf,s1+BPP(sf),x);      /* [0,1] */                     
  174.         r2 += (r = GET_R(sf,x));                                    
  175.         b2 += (b = GET_B(sf,x));                                    
  176.         y2 += (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);    
  177.         dy1[1] = yytab [y];                                         
  178.                                                                     
  179.         LOAD(sf,s2,x);              /* [1,0] */                     
  180.         r = GET_R(sf,x);                                            
  181.         b = GET_B(sf,x);                                            
  182.         y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b];            
  183.         dy2[0] = yytab [y];                                         
  184.                                                                     
  185.         LOAD(sf,s2+BPP(sf),x);      /* [1,1] */                     
  186.         r = GET_R(sf,x);                                            
  187.         b = GET_B(sf,x);                                            
  188.         y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b];            
  189.         dy2[1] = yytab [y];                                         
  190.                                                                     
  191.         /* average chromas: */                                      
  192.         dv[0] = vrytab [VMIN+(r2-y2)/2];                            
  193.         du[0] = ubytab [UMIN+(b2-y2)/2];                            
  194.     }
  195. /* CRM_00_11 (lower line) chroma resampling: */
  196. #define CONVERT_2x2_CHROMA_00_11(dy1,dy2,du,dv,sf,s1,s2)            
  197.     {                                                               
  198.         /* local variables: */                                      
  199.         PIXEL(sf,x);                                                
  200.         register unsigned int r, b, y;                              
  201.         register unsigned int r2, b2, y2;   /* 2nd line combined */ 
  202.                                                                     
  203.         /* process lumas: */                                        
  204.         LOAD(sf,s1,x);              /* [0,0] */                     
  205.         r = GET_R(sf,x);                                            
  206.         b = GET_B(sf,x);                                            
  207.         y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b];            
  208.         dy1[0] = yytab [y];                                         
  209.                                                                     
  210.         LOAD(sf,s1+BPP(sf),x);      /* [0,1] */                     
  211.         r = GET_R(sf,x);                                            
  212.         b = GET_B(sf,x);                                            
  213.         y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b];            
  214.         dy1[1] = yytab [y];                                         
  215.                                                                     
  216.         LOAD(sf,s2,x);              /* [1,0] */                     
  217.         r2 = (r = GET_R(sf,x));                                     
  218.         b2 = (b = GET_B(sf,x));                                     
  219.         y2 = (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);     
  220.         dy2[0] = yytab [y];                                         
  221.                                                                     
  222.         LOAD(sf,s2+BPP(sf),x);      /* [1,1] */                     
  223.         r2 += (r = GET_R(sf,x));                                    
  224.         b2 += (b = GET_B(sf,x));                                    
  225.         y2 += (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);    
  226.         dy2[1] = yytab [y];                                         
  227.                                                                     
  228.         /* average chromas: */                                      
  229.         dv[0] = vrytab [VMIN+(r2-y2)/2];                            
  230.         du[0] = ubytab [UMIN+(b2-y2)/2];                            
  231.     }
  232. /*
  233.  * Generic 2x2 block converter:
  234.  */
  235. #define CONVERT_2x2(dy1,dy2,du,dv,sf,s1,s2,crm)                     
  236.     CONVERT_2x2_##crm(dy1,dy2,du,dv,sf,s1,s2)
  237. /*
  238.  * Generic RGBtoYUV double-row converter:
  239.  *
  240.  *  YUV-image pointers are assumed to be 2x2-block aligned, as well as
  241.  *  n -- the number of pixels to be converter, is assumed to be multiple of 2.
  242.  */
  243. #define DBLROW(dy1,dy2,du,dv,sf,s1,s2,n,crm)                        
  244.     {                                                               
  245.         register int n2 = n/2;                                      
  246.         /* convert 2x2 blocks: */                                   
  247.         while (n2) {                                                
  248.             CONVERT_2x2(dy1,dy2,du,dv,sf,s1,s2,crm);                
  249.             dy1 += 2; dy2 += 2; du ++; dv ++;                       
  250.             s1 += BPP(sf) * 2; s2 += BPP(sf) * 2;                   
  251.             n2 --;                                                  
  252.         }                                                           
  253.     }
  254. /*
  255.  * Function names:
  256.  */
  257. #define FN(df,sf)               sf##to##df
  258. #define DBLROW_FN(df,sf,crm)    sf##to##df##_DBLROW_##crm
  259. /*
  260.  * Function replication macros:
  261.  *  (dblrow converters)
  262.  */
  263. #define DBLROW_FUNC(df,sf,crm)                                      
  264.     static void DBLROW_FN(df,sf,crm) (                              
  265.         unsigned char *dy1, unsigned char *dy2,                     
  266.         unsigned char *du, unsigned char *dv,                       
  267.         unsigned char *s1, unsigned char *s2, int n)                
  268.         DBLROW(dy1,dy2,du,dv,sf,s1,s2,n,crm)
  269. /***********************************************************/
  270. /*
  271.  * Actual double-row converters:
  272.  */
  273. DBLROW_FUNC(I420, RGB32,  CHROMA_11_11)
  274. DBLROW_FUNC(I420, RGB32,  CHROMA_11_00)
  275. DBLROW_FUNC(I420, RGB32,  CHROMA_00_11)
  276. DBLROW_FUNC(I420, BGR_32, CHROMA_11_11)
  277. DBLROW_FUNC(I420, BGR_32, CHROMA_11_00)
  278. DBLROW_FUNC(I420, BGR_32, CHROMA_00_11)
  279. DBLROW_FUNC(I420, RGB24,  CHROMA_11_11)
  280. DBLROW_FUNC(I420, RGB24,  CHROMA_11_00)
  281. DBLROW_FUNC(I420, RGB24,  CHROMA_00_11)
  282. DBLROW_FUNC(I420, BGR24,  CHROMA_11_11)
  283. DBLROW_FUNC(I420, BGR24,  CHROMA_11_00)
  284. DBLROW_FUNC(I420, BGR24,  CHROMA_00_11)
  285. DBLROW_FUNC(I420, RGB565, CHROMA_11_11)
  286. DBLROW_FUNC(I420, RGB565, CHROMA_11_00)
  287. DBLROW_FUNC(I420, RGB565, CHROMA_00_11)
  288. DBLROW_FUNC(I420, RGB555, CHROMA_11_11)
  289. DBLROW_FUNC(I420, RGB555, CHROMA_11_00)
  290. DBLROW_FUNC(I420, RGB555, CHROMA_00_11)
  291. DBLROW_FUNC(I420, RGB8,   CHROMA_11_11)
  292. DBLROW_FUNC(I420, RGB8,   CHROMA_11_00)
  293. DBLROW_FUNC(I420, RGB8,   CHROMA_00_11)
  294. /*
  295.  * Double-row scale function selection tables:
  296.  *  [source format][chroma resampling type]
  297.  */
  298. static void (* DblRowFuncs [RGB_FORMATS+2][CHROMA_RESAMPLING_MODES]) (
  299.     unsigned char *, unsigned char *, unsigned char *, unsigned char *,
  300.     unsigned char *, unsigned char *, int) =
  301. {
  302.     {
  303.         DBLROW_FN(I420, RGB32,  CHROMA_11_11),
  304.         DBLROW_FN(I420, RGB32,  CHROMA_11_00),
  305.         DBLROW_FN(I420, RGB32,  CHROMA_00_11)
  306.     },
  307.     {   /* BGR32: */
  308.         0, 0, 0
  309.     },
  310.     {
  311.         DBLROW_FN(I420, RGB24,  CHROMA_11_11),
  312.         DBLROW_FN(I420, RGB24,  CHROMA_11_00),
  313.         DBLROW_FN(I420, RGB24,  CHROMA_00_11)
  314.     },
  315.     {
  316.         DBLROW_FN(I420, RGB565, CHROMA_11_11),
  317.         DBLROW_FN(I420, RGB565, CHROMA_11_00),
  318.         DBLROW_FN(I420, RGB565, CHROMA_00_11)
  319.     },
  320.     {
  321.         DBLROW_FN(I420, RGB555, CHROMA_11_11),
  322.         DBLROW_FN(I420, RGB555, CHROMA_11_00),
  323.         DBLROW_FN(I420, RGB555, CHROMA_00_11)
  324.     },
  325.     {   /* RGB444: */
  326.         0, 0, 0
  327.     },
  328.     {
  329.         DBLROW_FN(I420, RGB8,   CHROMA_11_11),
  330.         DBLROW_FN(I420, RGB8,   CHROMA_11_00),
  331.         DBLROW_FN(I420, RGB8,   CHROMA_00_11)
  332.     },
  333.     {
  334.         DBLROW_FN(I420, BGR_32,  CHROMA_11_11),
  335.         DBLROW_FN(I420, BGR_32,  CHROMA_11_00),
  336.         DBLROW_FN(I420, BGR_32,  CHROMA_00_11)
  337.     },
  338.     {
  339.         DBLROW_FN(I420, BGR24,  CHROMA_11_11),
  340.         DBLROW_FN(I420, BGR24,  CHROMA_11_00),
  341.         DBLROW_FN(I420, BGR24,  CHROMA_00_11)
  342.     }
  343. };
  344. /*
  345.  * Bytes per pixel (bpp) table:
  346.  */
  347. static int bpp [RGB_FORMATS+2] =
  348. {
  349.     BPP(RGB32),
  350.     BPP(BGR32),
  351.     BPP(RGB24),
  352.     BPP(RGB565),
  353.     BPP(RGB555),
  354.     BPP(RGB444),
  355.     BPP(RGB8),
  356.     BPP(BGR_32),
  357.     BPP(BGR24)
  358. };
  359. /*
  360.  * The main RGBtoYUV converter:
  361.  */
  362. static int RGBtoYUV (
  363.     /* destination image parameters: */
  364.     unsigned char *dest_ptr, int dest_width, int dest_height,
  365.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  366.     /* source format: */
  367.     int src_format,
  368.     /* source image parametersBto: */
  369.     unsigned char *src_ptr, int src_width, int src_height,
  370.     int src_pitch, int src_x, int src_y, int src_dx, int src_dy)
  371. {
  372.     /* pointer to a double-row converter to use: */
  373.     void (*dblrow_proc) (unsigned char *, unsigned char *,
  374.         unsigned char *, unsigned char *, unsigned char *, unsigned char *, int);
  375.     /* pointers and source pixel depth: */
  376.     register unsigned char *dy1, *dy2, *du, *dv, *s1, *s2;
  377.     register int src_bpp, i;
  378.     /* check arguments: */
  379.     if (
  380.         /* alignments: */
  381.         ((unsigned)dest_ptr & 3) || (dest_pitch & 3) ||
  382.         ((unsigned)src_ptr  & 3) || (src_pitch  & 3) ||
  383.         /* image sizes: */
  384.         dest_width <= 0 || dest_height <= 0 ||
  385.         src_width  <= 0 || src_height  <= 0 ||
  386.         /* rectangles: */
  387.         dest_x < 0 || dest_y < 0 || dest_dx <= 0 || dest_dy <= 0 ||
  388.         src_x  < 0 || src_y  < 0 || src_dx  <= 0 || src_dy  <= 0 ||
  389.         /* overlaps: */
  390.         dest_width < dest_x + dest_dx || dest_height < dest_y + dest_dy ||
  391.         src_width  < src_x  + src_dx  || src_height  < src_y  + src_dy)
  392.     {
  393. fail:   /* fail: */
  394.         return -1;
  395.     }
  396.     /* check scale factors: */
  397.     if (dest_dx != src_dx || dest_dy != src_dy)
  398.         /* no in-place resizing !!! */
  399.         goto fail;
  400.     /* skip odd start column: */
  401.     if (dest_x & 1) { dest_x ++; dest_dx --; src_x ++; src_dx --; }
  402.     /* clip horisontal range: */
  403.     if (dest_dx & 1) { dest_dx --; src_dx --; if (dest_dx <= 0) goto fail;}
  404.     /* skip odd start row: */
  405.     if (dest_y & 1) { dest_y ++; dest_dy --; src_y ++; src_dy --; }
  406.     /* clip vertical range: */
  407.     if (dest_dy & 1) { dest_dy --; src_dy --; if (dest_dy <= 0) goto fail;}
  408.     /* select row and image converters: */
  409.     dblrow_proc = DblRowFuncs [src_format] [chroma_resampling_mode];
  410.     /* get source pixel depth: */
  411.     src_bpp = bpp [src_format];
  412.     /* check if bottop-up images: */
  413.     if (src_pitch < 0) src_ptr -= (src_height-1) * src_pitch;
  414.     if (dest_pitch <= 0) return -1;                     /* not supported */
  415.     /* get pointers: */
  416.     s1  = src_ptr + src_x * src_bpp + src_y * src_pitch;
  417.     s2  = s1 + src_pitch;
  418.     dy1 = dest_ptr + dest_x + dest_y * dest_pitch;      /* luma offsets  */
  419.     dy2 = dy1 + dest_pitch;
  420.     du  = dest_ptr + dest_height * dest_pitch
  421.           + (dest_x/2 + dest_y/2 * dest_pitch / 2);     /* chroma offset */
  422.     dv  = du + dest_height * dest_pitch / 4;
  423.     /* the main loop (processes 2 lines a time): */
  424.     for (i = 0; i < dest_dy/2; i ++) {
  425.         (*dblrow_proc) (dy1, dy2, du, dv, s1, s2, dest_dx);
  426.         /* switch to the next two lines: */
  427.         s1 += src_pitch * 2;    s2 += src_pitch * 2;
  428.         dy1 += dest_pitch * 2;  dy2 += dest_pitch * 2;
  429.         du += dest_pitch / 2;   dv += dest_pitch / 2;
  430.     }
  431.     /* success: */
  432.     return 0;
  433. }
  434. /*
  435.  * Public format-conversion routines.
  436.  * Use:
  437.  *  int XXXXtoYYYY (unsigned char *dest_ptr, int dest_width, int dest_height,
  438.  *      int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  439.  *      unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  440.  *      int src_x, int src_y, int src_dx, int src_dy);
  441.  * Input:
  442.  *  dest_ptr - pointer to a destination buffer
  443.  *  dest_width, dest_height - width/height of the destination image (pixels)
  444.  *  dest_pitch - pitch of the dest. buffer (in bytes; <0 - if bottom up image)
  445.  *  dest_x, dest_y, dest_dx, dest_dy - destination rectangle (pixels)
  446.  *  src_ptr - pointer to an input image
  447.  *  src_width, src_height - width/height of the input image (pixels)
  448.  *  src_pitch - pitch of the source buffer (in bytes; <0 - if bottom up image)
  449.  *  src_x, src_y, src_dx, src_dy - source rectangle (pixels)
  450.  * Returns:
  451.  *  0 - if success; -1 if failure.
  452.  * Note:
  453.  *  Both source and destination buffers must be 4-bytes aligned,
  454.  *  and their pitches (#of bytes in row) shall be multiple of 4!!!
  455.  */
  456. #define RGBTOYUV_FUNC(sf)                                   
  457.     int FN(I420,sf) (unsigned char *dest_ptr,               
  458.         int dest_width, int dest_height, int dest_pitch,    
  459.         int dest_x, int dest_y, int dest_dx, int dest_dy,   
  460.         unsigned char *src_ptr,                             
  461.         int src_width, int src_height, int src_pitch,       
  462.         int src_x, int src_y, int src_dx, int src_dy)       
  463.     {                                                       
  464.         return RGBtoYUV(                                  
  465.             dest_ptr, dest_width, dest_height,              
  466.             dest_pitch, dest_x, dest_y, dest_dx, dest_dy,   
  467.             ID(sf), src_ptr, src_width, src_height,         
  468.             src_pitch, src_x, src_y, src_dx, src_dy);       
  469.     }
  470. RGBTOYUV_FUNC(RGB32 )
  471. RGBTOYUV_FUNC(RGB24 )
  472. RGBTOYUV_FUNC(RGB565)
  473. RGBTOYUV_FUNC(RGB555)
  474. RGBTOYUV_FUNC(RGB8)
  475. RGBTOYUV_FUNC(BGR_32 )
  476. RGBTOYUV_FUNC(BGR24 )
  477. /*********************************
  478.  * Back to the old stuff: */
  479.  /*
  480.  * Checks format conversion parameters.
  481.  * Use:
  482.  *  int chk_args (unsigned char *dest_ptr, int dest_width, int dest_height,
  483.  *      int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  484.  *      unsigned char *src_ptr, int src_width, int src_height,
  485.  *      int src_pitch, int src_x, int src_y, int src_dx, int src_dy,
  486.  *      int *p_scale_x, int *p_scale_y);
  487.  * Input:
  488.  *  dest_ptr - pointer to a destination buffer
  489.  *  dest_width, dest_height - width/height of the destination image (pixels)
  490.  *  dest_pitch - pitch of the dest. buffer (in bytes; <0 - if bottom up image)
  491.  *  dest_x, dest_y, dest_dx, dest_dy - destination rectangle (pixels)
  492.  *  src_ptr - pointer to an input image
  493.  *  src_width, src_height - width/height of the input image (pixels)
  494.  *  src_pitch - pitch of the source buffer (in bytes; <0 - if bottom up image)
  495.  *  src_x, src_y, src_dx, src_dy - source rectangle (pixels)
  496.  * Output:
  497.  *  p_scale_x, p_scale_y - scale factors for x,y axes
  498.  *      (currently only 1:1, and 2:1 scale factors are allowed)
  499.  * Returns:
  500.  *  0 - if success; -1 if failure.
  501.  */
  502. static int
  503. chk_args (unsigned char *dest_ptr, int dest_width, int dest_height,
  504.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  505.     unsigned char *src_ptr, int src_width, int src_height,
  506.     int src_pitch, int src_x, int src_y, int src_dx, int src_dy,
  507.     int *p_scale_x, int *p_scale_y)
  508. {
  509.     /* alignments: */
  510.     if (((unsigned)dest_ptr & 3) || (dest_pitch & 3) ||
  511.         ((unsigned)src_ptr  & 3) || (src_pitch  & 3) ||
  512.     /* image sizes: */
  513.         dest_width <= 0 || dest_height <= 0 ||
  514.         src_width  <= 0 || src_height  <= 0 ||
  515.     /* rectangles: */
  516.         dest_x < 0 || dest_y < 0 || dest_dx <= 0 || dest_dy <= 0 ||
  517.         src_x  < 0 || src_y  < 0 || src_dx  <= 0 || src_dy  <= 0 ||
  518.     /* overlaps: */
  519.         dest_width < dest_x + dest_dx || dest_height < dest_y + dest_dy ||
  520.         src_width  < src_x  + src_dx  || src_height  < src_y  + src_dy)
  521.         goto fail;
  522.     /* scale factors: */
  523.     if (dest_dx == src_dx)          *p_scale_x = 1;
  524.     else if (dest_dx == 2 * src_dx) *p_scale_x = 2;
  525.     else goto fail;
  526.     if (dest_dy == src_dy)          *p_scale_y = 1;
  527.     else if (dest_dy == 2 * src_dy) *p_scale_y = 2;
  528.     else goto fail;
  529.     /* success: */
  530.     return 1;
  531.     /* failure: */
  532. fail:
  533.     return 0;
  534. }
  535. static int adjust_range (int *z1, int *dz1, int *z2, int *dz2, int inc2)
  536. {
  537.     /* skip odd start pixel: */
  538.     if (*z1 & 1) {
  539.         *z1 += 1;
  540.         *dz1 -= 1;
  541.         *z2 += inc2;
  542.         *dz2 -= inc2;
  543.     }
  544.     /* clip the range: */
  545.     if (*dz1 & 1) {
  546.         *dz1 -= 1;
  547.         *dz2 -= inc2;
  548.     }
  549.     return (*dz1 > 0 && *dz2 > 0);
  550. }
  551. //////////////////////////////////////////////////////
  552. //
  553. // ARGBtoYUVA
  554. //
  555. // Note: YUVA is identical to I420 but has an additional
  556. //   planar field at the end the contains "alpha" info.
  557. //   This "alpha" field is the size of the Y component
  558. //
  559. //////////////////////////////////////////////////////
  560. int ARGBtoYUVA (unsigned char *dest_ptr, int dest_width, int dest_height,
  561.     int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
  562.     unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
  563.     int src_x, int src_y, int src_dx, int src_dy)
  564. {
  565.     /* scale factors: */
  566.     int scale_x, scale_y;
  567.     /* check arguments: */
  568.     if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
  569.         dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
  570.         src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
  571.         return -1;
  572.     /* align destination rectangle: */
  573.     if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
  574.         !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
  575.         return 0;
  576.     /* check if bottom-up bitmaps: */
  577.     if (src_pitch < 0)  src_ptr -= (src_height-1) * src_pitch;
  578.     if (dest_pitch <= 0) return -1;     /* not supported */
  579. /*
  580.  *  if (!is_dest_alpha && !is_dest_beta && !is_dest_gamma && !is_dest_kappa)
  581.  */
  582.     {
  583.         /* just move data in, no color adjustments: */
  584.         unsigned char *s1, *s2, *d1, *d2, *dv, *du, *d3, *d4;
  585.         register int i, j;
  586.         /* get pointers: */
  587.         s1 = src_ptr + src_x * BPP(RGB32) + src_y * src_pitch; /* 3 bytes/pixel */
  588.         s2 = s1 + src_pitch;
  589.         d1 = dest_ptr + dest_x + dest_y * dest_pitch;    /* luma offsets  */
  590.         d2 = d1 + dest_pitch;
  591.         du = dest_ptr + dest_height * dest_pitch + (dest_x/2 + dest_y/2 * dest_pitch/2); /* chroma offset */
  592.         dv = du + dest_height * dest_pitch/4;
  593.         d3 = dv + dest_height * dest_pitch/4;
  594.         d4 = d3 + dest_pitch;
  595.         switch (chroma_resampling_mode)
  596.         {
  597.             case CRM_00_11:
  598.                 /* the main loop (processes 2 lines a time): */
  599.                 for (i = 0; i < dest_dy/2; i ++) {
  600.                     /* convert 2x2 block: */
  601.                     for (j = 0; j < dest_dx/2; j ++) {
  602.                         int r2, b2, y2;
  603.                         /* process lumas: */
  604.                         {
  605.                             PIXEL(RGB32,x);
  606.                             register unsigned int r, b, y;
  607.                             LOAD(RGB32,s1,x);               /* [0,0] */
  608.                             r = GET_R(RGB32,x);
  609.                             b = GET_B(RGB32,x);
  610.                             y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b];
  611.                             d1[0] = yytab [y];
  612. d3[0] = GET_A(RGB32,x);
  613.                             LOAD(RGB32,s1+BPP(RGB32),x);    /* [0,1] */
  614.                             r = GET_R(RGB32,x);
  615.                             b = GET_B(RGB32,x);
  616.                             y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b];
  617.                             d1[1] = yytab [y];
  618. d3[1] = GET_A(RGB32,x);
  619.                             LOAD(RGB32,s2,x);               /* [1,0] */
  620.                             r2 = (r = GET_R(RGB32,x));
  621.                             b2 = (b = GET_B(RGB32,x));
  622.                             y2 = (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
  623.                             d2[0] = yytab [y];
  624. d4[0] = GET_A(RGB32,x);
  625.                             LOAD(RGB32,s2+BPP(RGB32),x);    /* [1,1] */
  626.                             r2 += (r = GET_R(RGB32,x));
  627.                             b2 += (b = GET_B(RGB32,x));
  628.                             y2 += (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
  629.                             d2[1] = yytab [y];
  630. d4[1] = GET_A(RGB32,x);
  631.                         }
  632.                         /* average chromas: */
  633.                         dv[0] = vrytab [VMIN+(r2-y2)/2];
  634.                         du[0] = ubytab [UMIN+(b2-y2)/2];
  635.                         /* go to the next block: */
  636.                         s1 += 2 * BPP(RGB32); s2 += 2 * BPP(RGB32);
  637.                         d1 += 2; d2 += 2;
  638.                         d3 += 2; d4 += 2;
  639.                         du += 1; dv += 1;
  640.                     }
  641.                     /* switch to the next two lines: */
  642.                     s1 += src_pitch * 2 - dest_dx * BPP(RGB32);
  643.                     s2 += src_pitch * 2 - dest_dx * BPP(RGB32);
  644.                     d1 += dest_pitch * 2 - dest_dx;
  645.                     d2 += dest_pitch * 2 - dest_dx;
  646.                     d3 += dest_pitch * 2 - dest_dx;
  647.                     d4 += dest_pitch * 2 - dest_dx;
  648.                     du += (dest_pitch - dest_dx)/2;
  649.                     dv += (dest_pitch - dest_dx)/2;
  650.                 }
  651.                 break;
  652.             case CRM_11_00:
  653.                 /* the main loop (processes 2 lines a time): */
  654.                 for (i = 0; i < dest_dy/2; i ++) {
  655.                     /* convert 2x2 block: */
  656.                     for (j = 0; j < dest_dx/2; j ++) {
  657.                         int r2, b2, y2;
  658.                         /* process lumas: */
  659.                         {
  660.                             PIXEL(RGB32,x);
  661.                             register unsigned int r, b, y;
  662.                             LOAD(RGB32,s1,x);               /* [0,0] */
  663.                             r2 = (r = GET_R(RGB32,x));
  664.                             b2 = (b = GET_B(RGB32,x));
  665.                             y2 = (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
  666.                             d1[0] = yytab [y];
  667. d3[0] = GET_A(RGB32,x);
  668.                             LOAD(RGB32,s1+BPP(RGB32),x);    /* [0,1] */
  669.                             r2 += (r = GET_R(RGB32,x));
  670.                             b2 += (b = GET_B(RGB32,x));
  671.                             y2 += (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
  672.                             d1[1] = yytab [y];
  673. d3[1] = GET_A(RGB32,x);
  674.                             LOAD(RGB32,s2,x);               /* [1,0] */
  675.                             r = GET_R(RGB32,x);
  676.                             b = GET_B(RGB32,x);
  677.                             y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b];
  678.                             d2[0] = yytab [y];
  679. d4[0] = GET_A(RGB32,x);
  680.                             LOAD(RGB32,s2+BPP(RGB32),x);    /* [1,1] */
  681.                             r = GET_R(RGB32,x);
  682.                             b = GET_B(RGB32,x);
  683.                             y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b];
  684.                             d2[1] = yytab [y];
  685.   d4[1] = GET_A(RGB32,x);
  686.                        }
  687.                         /* average chromas: */
  688.                         dv[0] = vrytab [VMIN+(r2-y2)/2];
  689.                         du[0] = ubytab [UMIN+(b2-y2)/2];
  690.                         /* go to the next block: */
  691.                         s1 += 2 * BPP(RGB32); s2 += 2 * BPP(RGB32);
  692.                         d1 += 2; d2 += 2;
  693.                         d3 += 2; d4 += 2;
  694.                         du += 1; dv += 1;
  695.                     }
  696.                     /* switch to the next two lines: */
  697.                     s1 += src_pitch * 2 - dest_dx * BPP(RGB32);
  698.                     s2 += src_pitch * 2 - dest_dx * BPP(RGB32);
  699.                     d1 += dest_pitch * 2 - dest_dx;
  700.                     d2 += dest_pitch * 2 - dest_dx;
  701.                     d3 += dest_pitch * 2 - dest_dx;
  702.                     d4 += dest_pitch * 2 - dest_dx;
  703.                     du += (dest_pitch - dest_dx)/2;
  704.                     dv += (dest_pitch - dest_dx)/2;
  705.                 }
  706.                 break;
  707.             case CRM_11_11:
  708.             default:
  709.                 /* the main loop (processes 2 lines a time): */
  710.                 for (i = 0; i < dest_dy/2; i ++) {
  711.                     /* convert 2x2 block: */
  712.                     for (j = 0; j < dest_dx/2; j ++) {
  713.                         int r4, b4, y4;
  714.                         /* process lumas: */
  715.                         {
  716.                             PIXEL(RGB32,x);
  717.                             register unsigned int r, b, y;
  718.                             LOAD(RGB32,s1,x);               /* [0,0] */
  719.                             r4 = (r = GET_R(RGB32,x));
  720.                             b4 = (b = GET_B(RGB32,x));
  721.                             y4 = (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
  722.                             d1[0] = yytab [y];
  723. d3[0] = GET_A(RGB32,x);
  724.                             LOAD(RGB32,s1+BPP(RGB32),x);    /* [0,1] */
  725.                             r4 += (r = GET_R(RGB32,x));
  726.                             b4 += (b = GET_B(RGB32,x));
  727.                             y4 += (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
  728.                             d1[1] = yytab [y];
  729. d3[1] = GET_A(RGB32,x);
  730.                             LOAD(RGB32,s2,x);               /* [1,0] */
  731.                             r4 += (r = GET_R(RGB32,x));
  732.                             b4 += (b = GET_B(RGB32,x));
  733.                             y4 += (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
  734.                             d2[0] = yytab [y];
  735. d4[0] = GET_A(RGB32,x);
  736.                             LOAD(RGB32,s2+BPP(RGB32),x);    /* [1,1] */
  737.                             r4 += (r = GET_R(RGB32,x));
  738.                             b4 += (b = GET_B(RGB32,x));
  739.                             y4 += (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
  740.                             d2[1] = yytab [y];
  741. d4[1] = GET_A(RGB32,x);
  742.                         }
  743.                         /* average chromas: */
  744.                         dv[0] = vrytab [VMIN+(r4-y4)/4];
  745.                         du[0] = ubytab [UMIN+(b4-y4)/4];
  746.                         /* go to the next block: */
  747.                         s1 += 2 * BPP(RGB32); s2 += 2 * BPP(RGB32);
  748.                         d1 += 2; d2 += 2;
  749.                         d3 += 2; d4 += 2;
  750.                         du += 1; dv += 1;
  751.                     }
  752.                     /* switch to the next two lines: */
  753.                     s1 += src_pitch * 2 - dest_dx * BPP(RGB32);
  754.                     s2 += src_pitch * 2 - dest_dx * BPP(RGB32);
  755.                     d1 += dest_pitch * 2 - dest_dx;
  756.                     d2 += dest_pitch * 2 - dest_dx;
  757.                     d3 += dest_pitch * 2 - dest_dx;
  758.                     d4 += dest_pitch * 2 - dest_dx;
  759.                     du += (dest_pitch - dest_dx)/2;
  760.                     dv += (dest_pitch - dest_dx)/2;
  761.                 }
  762.         }
  763.     }
  764. /*
  765.  *  else {
  766.  *      put all the color-dependent stuff here ...
  767.  *  }
  768.  */
  769.     return 0;
  770. }
  771. /* rgb2yuv.c -- end of file */