rgb2yuv.c
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:35k
源码类别:

Symbian

开发平台:

C/C++

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