rgb2yuv.c
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:36k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: rgb2yuv.c,v 1.2.48.1 2004/07/09 02:00:18 hubbe Exp $
- *
- * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file,
- * are subject to the current version of the RealNetworks Public
- * Source License (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (the "RCSL") available at
- * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
- * will apply. You may also obtain the license terms directly from
- * RealNetworks. You may not use this file except in compliance with
- * the RPSL or, if you have a valid RCSL with RealNetworks applicable
- * to this file, the RCSL. Please see the applicable RPSL or RCSL for
- * the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the
- * portions it created.
- *
- * This file, and the files included with this file, is distributed
- * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
- * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
- * ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- /*** #includes: ********************************************/
- #include "env.h"
- #include "rgb.h" /* basic RGB-data definitions & macros */
- #include "yuv.h" /* YUV-to-RGB conversion tables & macros */
- #include "clip.h" /* macros for clipping & dithering */
- #include "scale.h" /* scale algorithms */
- #include "colorlib.h"
- /*** RGB to YUV color converters: **************************/
- /*
- * These functions were borrowed from our "old" color conversion library,
- * and they do not support things like stretching or color adjustments.
- * Given some more time this module should be completely rewritten.
- *
- ***************/
- /*-----------------2/24/2002 7:45AM-----------------
- * Replaced the old code with macros.
- * In-place resizing and color adjustments are not added since nobody
- * really asked for it, and it would have blown the code by factor of 6 (at least).
- * Yuriy.
- * --------------------------------------------------*/
- /*-----------------9/19/2002 2:06PM-----------------
- * Added support for byte-swapped RGB32 (BGR_32) and BGR24 input formats.
- * To avoid changes (table reordering) in other modules, the definitions
- * related to these formats are placed here, instead of "rgb.h".
- * Yuriy.
- * --------------------------------------------------*/
- /* new RGB format IDs: */
- #define BGR_32_ID RGB_FORMATS
- #define BGR24_ID (RGB_FORMATS + 1)
- /* bytes per pixel: */
- #define BGR_32_BPP 4
- #define BGR24_BPP 3
- /* local pixel representations: */
- #define BGR_32_PIXEL(a) RGBX_PIXEL(a)
- #define BGR24_PIXEL(a) RGB24_PIXEL(a)
- /* load/store/copy pixel macros: */
- #define BGR_32_LOAD(s,a) RGBX_LOAD(s,a,unsigned int)
- #define BGR_32_STORE(d,a) RGBX_STORE(d,a,unsigned int)
- #define BGR_32_COPY(da,sa) RGBX_COPY(da,sa)
- #define BGR24_LOAD(s,a) a##_r=(s)[0], a##_g=(s)[1], a##_b=(s)[2]
- #define BGR24_STORE(d,a) (d)[0]=a##_r, (d)[1]=a##_g, (d)[2]=a##_b
- #define BGR24_COPY(da,sa) da##_r=sa##_r, da##_g=sa##_g, da##_b=sa##_b
- /* BGR_32 bit fields: 0xBBGGRR00: */
- #define BGR_32_R_START 8
- #define BGR_32_R_BITS 8
- #define BGR_32_G_START 16
- #define BGR_32_G_BITS 8
- #define BGR_32_B_START 24
- #define BGR_32_B_BITS 8
- /* fields extraction/assignment macros: */
- #define BGR_32_GET_R(a) RGBX_GET_X(BGR_32,R,a)
- #define BGR_32_GET_G(a) RGBX_GET_X(BGR_32,G,a)
- #define BGR_32_GET_B(a) RGBX_GET_X(BGR_32,B,a)
- #define BGR_32_SET(a,r,g,b) RGBX_SET( BGR_32,a,r,g,b)
- #define BGR24_GET_R(a) (a##_r)
- #define BGR24_GET_G(a) (a##_g)
- #define BGR24_GET_B(a) (a##_b)
- #define BGR24_SET(a,r,g,b) a##_b=(b), a##_g=(g), a##_r=(r)
- /***************************************************************/
- /*
- * YUV 4:2:0 chroma resampling modes:
- * Input chroma a b
- * samples: c d
- *
- * CRM_11_11: (a+b+c+d) / 4
- * CRM_11_00: (a+b) / 2
- * CRM_00_11: (c+d) / 2
- */
- #define CHROMA_RESAMPLING_MODES 3
- /*
- * 2x2-block load-convert-store macros:
- */
- /* CRM_11_11 (both lines) chroma resampling: */
- #define CONVERT_2x2_CHROMA_11_11(dy1,dy2,du,dv,sf,s1,s2)
- {
- /* local variables: */
- PIXEL(sf,x);
- register unsigned int r, b, y;
- register unsigned int r4, b4, y4; /* combined quant-s */
-
- /* process lumas: */
- LOAD(sf,s1,x); /* [0,0] */
- r4 = (r = GET_R(sf,x));
- b4 = (b = GET_B(sf,x));
- y4 = (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);
- dy1[0] = yytab [y];
-
- LOAD(sf,s1+BPP(sf),x); /* [0,1] */
- r4 += (r = GET_R(sf,x));
- b4 += (b = GET_B(sf,x));
- y4 += (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);
- dy1[1] = yytab [y];
-
- LOAD(sf,s2,x); /* [1,0] */
- r4 += (r = GET_R(sf,x));
- b4 += (b = GET_B(sf,x));
- y4 += (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);
- dy2[0] = yytab [y];
-
- LOAD(sf,s2+BPP(sf),x); /* [1,1] */
- r4 += (r = GET_R(sf,x));
- b4 += (b = GET_B(sf,x));
- y4 += (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);
- dy2[1] = yytab [y];
-
- /* average chromas: */
- dv[0] = vrytab [VMIN+(r4-y4)/4];
- du[0] = ubytab [UMIN+(b4-y4)/4];
- }
- /* CRM_11_00 (upper line) chroma resampling: */
- #define CONVERT_2x2_CHROMA_11_00(dy1,dy2,du,dv,sf,s1,s2)
- {
- /* local variables: */
- PIXEL(sf,x);
- register unsigned int r, b, y;
- register unsigned int r2, b2, y2; /* 1st line combined */
-
- /* process lumas: */
- LOAD(sf,s1,x); /* [0,0] */
- r2 = (r = GET_R(sf,x));
- b2 = (b = GET_B(sf,x));
- y2 = (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);
- dy1[0] = yytab [y];
-
- LOAD(sf,s1+BPP(sf),x); /* [0,1] */
- r2 += (r = GET_R(sf,x));
- b2 += (b = GET_B(sf,x));
- y2 += (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);
- dy1[1] = yytab [y];
-
- LOAD(sf,s2,x); /* [1,0] */
- r = GET_R(sf,x);
- b = GET_B(sf,x);
- y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b];
- dy2[0] = yytab [y];
-
- LOAD(sf,s2+BPP(sf),x); /* [1,1] */
- r = GET_R(sf,x);
- b = GET_B(sf,x);
- y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b];
- dy2[1] = yytab [y];
-
- /* average chromas: */
- dv[0] = vrytab [VMIN+(r2-y2)/2];
- du[0] = ubytab [UMIN+(b2-y2)/2];
- }
- /* CRM_00_11 (lower line) chroma resampling: */
- #define CONVERT_2x2_CHROMA_00_11(dy1,dy2,du,dv,sf,s1,s2)
- {
- /* local variables: */
- PIXEL(sf,x);
- register unsigned int r, b, y;
- register unsigned int r2, b2, y2; /* 2nd line combined */
-
- /* process lumas: */
- LOAD(sf,s1,x); /* [0,0] */
- r = GET_R(sf,x);
- b = GET_B(sf,x);
- y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b];
- dy1[0] = yytab [y];
-
- LOAD(sf,s1+BPP(sf),x); /* [0,1] */
- r = GET_R(sf,x);
- b = GET_B(sf,x);
- y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b];
- dy1[1] = yytab [y];
-
- LOAD(sf,s2,x); /* [1,0] */
- r2 = (r = GET_R(sf,x));
- b2 = (b = GET_B(sf,x));
- y2 = (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);
- dy2[0] = yytab [y];
-
- LOAD(sf,s2+BPP(sf),x); /* [1,1] */
- r2 += (r = GET_R(sf,x));
- b2 += (b = GET_B(sf,x));
- y2 += (y = yrtab [r] + ygtab [GET_G(sf,x)] + ybtab [b]);
- dy2[1] = yytab [y];
-
- /* average chromas: */
- dv[0] = vrytab [VMIN+(r2-y2)/2];
- du[0] = ubytab [UMIN+(b2-y2)/2];
- }
- /*
- * Generic 2x2 block converter:
- */
- #define CONVERT_2x2(dy1,dy2,du,dv,sf,s1,s2,crm)
- CONVERT_2x2_##crm(dy1,dy2,du,dv,sf,s1,s2)
- /*
- * Generic RGBtoYUV double-row converter:
- *
- * YUV-image pointers are assumed to be 2x2-block aligned, as well as
- * n -- the number of pixels to be converter, is assumed to be multiple of 2.
- */
- #define DBLROW(dy1,dy2,du,dv,sf,s1,s2,n,crm)
- {
- register int n2 = n/2;
- /* convert 2x2 blocks: */
- while (n2) {
- CONVERT_2x2(dy1,dy2,du,dv,sf,s1,s2,crm);
- dy1 += 2; dy2 += 2; du ++; dv ++;
- s1 += BPP(sf) * 2; s2 += BPP(sf) * 2;
- n2 --;
- }
- }
- /*
- * Function names:
- */
- #define FN(df,sf) sf##to##df
- #define DBLROW_FN(df,sf,crm) sf##to##df##_DBLROW_##crm
- /*
- * Function replication macros:
- * (dblrow converters)
- */
- #define DBLROW_FUNC(df,sf,crm)
- static void DBLROW_FN(df,sf,crm) (
- unsigned char *dy1, unsigned char *dy2,
- unsigned char *du, unsigned char *dv,
- unsigned char *s1, unsigned char *s2, int n)
- DBLROW(dy1,dy2,du,dv,sf,s1,s2,n,crm)
- /***********************************************************/
- /*
- * Actual double-row converters:
- */
- DBLROW_FUNC(I420, RGB32, CHROMA_11_11)
- DBLROW_FUNC(I420, RGB32, CHROMA_11_00)
- DBLROW_FUNC(I420, RGB32, CHROMA_00_11)
- DBLROW_FUNC(I420, BGR_32, CHROMA_11_11)
- DBLROW_FUNC(I420, BGR_32, CHROMA_11_00)
- DBLROW_FUNC(I420, BGR_32, CHROMA_00_11)
- DBLROW_FUNC(I420, RGB24, CHROMA_11_11)
- DBLROW_FUNC(I420, RGB24, CHROMA_11_00)
- DBLROW_FUNC(I420, RGB24, CHROMA_00_11)
- DBLROW_FUNC(I420, BGR24, CHROMA_11_11)
- DBLROW_FUNC(I420, BGR24, CHROMA_11_00)
- DBLROW_FUNC(I420, BGR24, CHROMA_00_11)
- DBLROW_FUNC(I420, RGB565, CHROMA_11_11)
- DBLROW_FUNC(I420, RGB565, CHROMA_11_00)
- DBLROW_FUNC(I420, RGB565, CHROMA_00_11)
- DBLROW_FUNC(I420, RGB555, CHROMA_11_11)
- DBLROW_FUNC(I420, RGB555, CHROMA_11_00)
- DBLROW_FUNC(I420, RGB555, CHROMA_00_11)
- DBLROW_FUNC(I420, RGB8, CHROMA_11_11)
- DBLROW_FUNC(I420, RGB8, CHROMA_11_00)
- DBLROW_FUNC(I420, RGB8, CHROMA_00_11)
- /*
- * Double-row scale function selection tables:
- * [source format][chroma resampling type]
- */
- static void (* DblRowFuncs [RGB_FORMATS+2][CHROMA_RESAMPLING_MODES]) (
- unsigned char *, unsigned char *, unsigned char *, unsigned char *,
- unsigned char *, unsigned char *, int) =
- {
- {
- DBLROW_FN(I420, RGB32, CHROMA_11_11),
- DBLROW_FN(I420, RGB32, CHROMA_11_00),
- DBLROW_FN(I420, RGB32, CHROMA_00_11)
- },
- { /* BGR32: */
- 0, 0, 0
- },
- {
- DBLROW_FN(I420, RGB24, CHROMA_11_11),
- DBLROW_FN(I420, RGB24, CHROMA_11_00),
- DBLROW_FN(I420, RGB24, CHROMA_00_11)
- },
- {
- DBLROW_FN(I420, RGB565, CHROMA_11_11),
- DBLROW_FN(I420, RGB565, CHROMA_11_00),
- DBLROW_FN(I420, RGB565, CHROMA_00_11)
- },
- {
- DBLROW_FN(I420, RGB555, CHROMA_11_11),
- DBLROW_FN(I420, RGB555, CHROMA_11_00),
- DBLROW_FN(I420, RGB555, CHROMA_00_11)
- },
- { /* RGB444: */
- 0, 0, 0
- },
- {
- DBLROW_FN(I420, RGB8, CHROMA_11_11),
- DBLROW_FN(I420, RGB8, CHROMA_11_00),
- DBLROW_FN(I420, RGB8, CHROMA_00_11)
- },
- {
- DBLROW_FN(I420, BGR_32, CHROMA_11_11),
- DBLROW_FN(I420, BGR_32, CHROMA_11_00),
- DBLROW_FN(I420, BGR_32, CHROMA_00_11)
- },
- {
- DBLROW_FN(I420, BGR24, CHROMA_11_11),
- DBLROW_FN(I420, BGR24, CHROMA_11_00),
- DBLROW_FN(I420, BGR24, CHROMA_00_11)
- }
- };
- /*
- * Bytes per pixel (bpp) table:
- */
- static int bpp [RGB_FORMATS+2] =
- {
- BPP(RGB32),
- BPP(BGR32),
- BPP(RGB24),
- BPP(RGB565),
- BPP(RGB555),
- BPP(RGB444),
- BPP(RGB8),
- BPP(BGR_32),
- BPP(BGR24)
- };
- /*
- * The main RGBtoYUV converter:
- */
- static int RGBtoYUV (
- /* destination image parameters: */
- unsigned char *dest_ptr, int dest_width, int dest_height,
- int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
- /* source format: */
- int src_format,
- /* source image parametersBto: */
- unsigned char *src_ptr, int src_width, int src_height,
- int src_pitch, int src_x, int src_y, int src_dx, int src_dy)
- {
- /* pointer to a double-row converter to use: */
- void (*dblrow_proc) (unsigned char *, unsigned char *,
- unsigned char *, unsigned char *, unsigned char *, unsigned char *, int);
- /* pointers and source pixel depth: */
- register unsigned char *dy1, *dy2, *du, *dv, *s1, *s2;
- register int src_bpp, i;
- /* check arguments: */
- if (
- /* alignments: */
- ((unsigned)dest_ptr & 3) || (dest_pitch & 3) ||
- ((unsigned)src_ptr & 3) || (src_pitch & 3) ||
- /* image sizes: */
- dest_width <= 0 || dest_height <= 0 ||
- src_width <= 0 || src_height <= 0 ||
- /* rectangles: */
- dest_x < 0 || dest_y < 0 || dest_dx <= 0 || dest_dy <= 0 ||
- src_x < 0 || src_y < 0 || src_dx <= 0 || src_dy <= 0 ||
- /* overlaps: */
- dest_width < dest_x + dest_dx || dest_height < dest_y + dest_dy ||
- src_width < src_x + src_dx || src_height < src_y + src_dy)
- {
- fail: /* fail: */
- return -1;
- }
- /* check scale factors: */
- if (dest_dx != src_dx || dest_dy != src_dy)
- /* no in-place resizing !!! */
- goto fail;
- /* skip odd start column: */
- if (dest_x & 1) { dest_x ++; dest_dx --; src_x ++; src_dx --; }
- /* clip horisontal range: */
- if (dest_dx & 1) { dest_dx --; src_dx --; if (dest_dx <= 0) goto fail;}
- /* skip odd start row: */
- if (dest_y & 1) { dest_y ++; dest_dy --; src_y ++; src_dy --; }
- /* clip vertical range: */
- if (dest_dy & 1) { dest_dy --; src_dy --; if (dest_dy <= 0) goto fail;}
- /* select row and image converters: */
- dblrow_proc = DblRowFuncs [src_format] [chroma_resampling_mode];
- /* get source pixel depth: */
- src_bpp = bpp [src_format];
- /* check if bottop-up images: */
- if (src_pitch < 0) src_ptr -= (src_height-1) * src_pitch;
- if (dest_pitch <= 0) return -1; /* not supported */
- /* get pointers: */
- s1 = src_ptr + src_x * src_bpp + src_y * src_pitch;
- s2 = s1 + src_pitch;
- dy1 = dest_ptr + dest_x + dest_y * dest_pitch; /* luma offsets */
- dy2 = dy1 + dest_pitch;
- du = dest_ptr + dest_height * dest_pitch
- + (dest_x/2 + dest_y/2 * dest_pitch / 2); /* chroma offset */
- dv = du + dest_height * dest_pitch / 4;
- /* the main loop (processes 2 lines a time): */
- for (i = 0; i < dest_dy/2; i ++) {
- (*dblrow_proc) (dy1, dy2, du, dv, s1, s2, dest_dx);
- /* switch to the next two lines: */
- s1 += src_pitch * 2; s2 += src_pitch * 2;
- dy1 += dest_pitch * 2; dy2 += dest_pitch * 2;
- du += dest_pitch / 2; dv += dest_pitch / 2;
- }
- /* success: */
- return 0;
- }
- /*
- * Public format-conversion routines.
- * Use:
- * int XXXXtoYYYY (unsigned char *dest_ptr, int dest_width, int dest_height,
- * int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
- * unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
- * int src_x, int src_y, int src_dx, int src_dy);
- * Input:
- * dest_ptr - pointer to a destination buffer
- * dest_width, dest_height - width/height of the destination image (pixels)
- * dest_pitch - pitch of the dest. buffer (in bytes; <0 - if bottom up image)
- * dest_x, dest_y, dest_dx, dest_dy - destination rectangle (pixels)
- * src_ptr - pointer to an input image
- * src_width, src_height - width/height of the input image (pixels)
- * src_pitch - pitch of the source buffer (in bytes; <0 - if bottom up image)
- * src_x, src_y, src_dx, src_dy - source rectangle (pixels)
- * Returns:
- * 0 - if success; -1 if failure.
- * Note:
- * Both source and destination buffers must be 4-bytes aligned,
- * and their pitches (#of bytes in row) shall be multiple of 4!!!
- */
- #define RGBTOYUV_FUNC(sf)
- int FN(I420,sf) (unsigned char *dest_ptr,
- int dest_width, int dest_height, int dest_pitch,
- int dest_x, int dest_y, int dest_dx, int dest_dy,
- unsigned char *src_ptr,
- int src_width, int src_height, int src_pitch,
- int src_x, int src_y, int src_dx, int src_dy)
- {
- return RGBtoYUV(
- dest_ptr, dest_width, dest_height,
- dest_pitch, dest_x, dest_y, dest_dx, dest_dy,
- ID(sf), src_ptr, src_width, src_height,
- src_pitch, src_x, src_y, src_dx, src_dy);
- }
- RGBTOYUV_FUNC(RGB32 )
- RGBTOYUV_FUNC(RGB24 )
- RGBTOYUV_FUNC(RGB565)
- RGBTOYUV_FUNC(RGB555)
- RGBTOYUV_FUNC(RGB8)
- RGBTOYUV_FUNC(BGR_32 )
- RGBTOYUV_FUNC(BGR24 )
- /*********************************
- * Back to the old stuff: */
- /*
- * Checks format conversion parameters.
- * Use:
- * int chk_args (unsigned char *dest_ptr, int dest_width, int dest_height,
- * int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
- * unsigned char *src_ptr, int src_width, int src_height,
- * int src_pitch, int src_x, int src_y, int src_dx, int src_dy,
- * int *p_scale_x, int *p_scale_y);
- * Input:
- * dest_ptr - pointer to a destination buffer
- * dest_width, dest_height - width/height of the destination image (pixels)
- * dest_pitch - pitch of the dest. buffer (in bytes; <0 - if bottom up image)
- * dest_x, dest_y, dest_dx, dest_dy - destination rectangle (pixels)
- * src_ptr - pointer to an input image
- * src_width, src_height - width/height of the input image (pixels)
- * src_pitch - pitch of the source buffer (in bytes; <0 - if bottom up image)
- * src_x, src_y, src_dx, src_dy - source rectangle (pixels)
- * Output:
- * p_scale_x, p_scale_y - scale factors for x,y axes
- * (currently only 1:1, and 2:1 scale factors are allowed)
- * Returns:
- * 0 - if success; -1 if failure.
- */
- static int
- chk_args (unsigned char *dest_ptr, int dest_width, int dest_height,
- int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
- unsigned char *src_ptr, int src_width, int src_height,
- int src_pitch, int src_x, int src_y, int src_dx, int src_dy,
- int *p_scale_x, int *p_scale_y)
- {
- /* alignments: */
- if (((unsigned)dest_ptr & 3) || (dest_pitch & 3) ||
- ((unsigned)src_ptr & 3) || (src_pitch & 3) ||
- /* image sizes: */
- dest_width <= 0 || dest_height <= 0 ||
- src_width <= 0 || src_height <= 0 ||
- /* rectangles: */
- dest_x < 0 || dest_y < 0 || dest_dx <= 0 || dest_dy <= 0 ||
- src_x < 0 || src_y < 0 || src_dx <= 0 || src_dy <= 0 ||
- /* overlaps: */
- dest_width < dest_x + dest_dx || dest_height < dest_y + dest_dy ||
- src_width < src_x + src_dx || src_height < src_y + src_dy)
- goto fail;
- /* scale factors: */
- if (dest_dx == src_dx) *p_scale_x = 1;
- else if (dest_dx == 2 * src_dx) *p_scale_x = 2;
- else goto fail;
- if (dest_dy == src_dy) *p_scale_y = 1;
- else if (dest_dy == 2 * src_dy) *p_scale_y = 2;
- else goto fail;
- /* success: */
- return 1;
- /* failure: */
- fail:
- return 0;
- }
- static int adjust_range (int *z1, int *dz1, int *z2, int *dz2, int inc2)
- {
- /* skip odd start pixel: */
- if (*z1 & 1) {
- *z1 += 1;
- *dz1 -= 1;
- *z2 += inc2;
- *dz2 -= inc2;
- }
- /* clip the range: */
- if (*dz1 & 1) {
- *dz1 -= 1;
- *dz2 -= inc2;
- }
- return (*dz1 > 0 && *dz2 > 0);
- }
- //////////////////////////////////////////////////////
- //
- // ARGBtoYUVA
- //
- // Note: YUVA is identical to I420 but has an additional
- // planar field at the end the contains "alpha" info.
- // This "alpha" field is the size of the Y component
- //
- //////////////////////////////////////////////////////
- int ARGBtoYUVA (unsigned char *dest_ptr, int dest_width, int dest_height,
- int dest_pitch, int dest_x, int dest_y, int dest_dx, int dest_dy,
- unsigned char *src_ptr, int src_width, int src_height, int src_pitch,
- int src_x, int src_y, int src_dx, int src_dy)
- {
- /* scale factors: */
- int scale_x, scale_y;
- /* check arguments: */
- if (!chk_args (dest_ptr, dest_width, dest_height, dest_pitch,
- dest_x, dest_y, dest_dx, dest_dy, src_ptr, src_width, src_height,
- src_pitch, src_x, src_y, src_dx, src_dy, &scale_x, &scale_y))
- return -1;
- /* align destination rectangle: */
- if (!adjust_range (&dest_x, &dest_dx, &src_x, &src_dx, scale_x) ||
- !adjust_range (&dest_y, &dest_dy, &src_y, &src_dy, scale_y))
- return 0;
- /* check if bottom-up bitmaps: */
- if (src_pitch < 0) src_ptr -= (src_height-1) * src_pitch;
- if (dest_pitch <= 0) return -1; /* not supported */
- /*
- * if (!is_dest_alpha && !is_dest_beta && !is_dest_gamma && !is_dest_kappa)
- */
- {
- /* just move data in, no color adjustments: */
- unsigned char *s1, *s2, *d1, *d2, *dv, *du, *d3, *d4;
- register int i, j;
- /* get pointers: */
- s1 = src_ptr + src_x * BPP(RGB32) + src_y * src_pitch; /* 3 bytes/pixel */
- s2 = s1 + src_pitch;
- d1 = dest_ptr + dest_x + dest_y * dest_pitch; /* luma offsets */
- d2 = d1 + dest_pitch;
- du = dest_ptr + dest_height * dest_pitch + (dest_x/2 + dest_y/2 * dest_pitch/2); /* chroma offset */
- dv = du + dest_height * dest_pitch/4;
- d3 = dv + dest_height * dest_pitch/4;
- d4 = d3 + dest_pitch;
- switch (chroma_resampling_mode)
- {
- case CRM_00_11:
- /* the main loop (processes 2 lines a time): */
- for (i = 0; i < dest_dy/2; i ++) {
- /* convert 2x2 block: */
- for (j = 0; j < dest_dx/2; j ++) {
- int r2, b2, y2;
- /* process lumas: */
- {
- PIXEL(RGB32,x);
- register unsigned int r, b, y;
- LOAD(RGB32,s1,x); /* [0,0] */
- r = GET_R(RGB32,x);
- b = GET_B(RGB32,x);
- y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b];
- d1[0] = yytab [y];
- d3[0] = GET_A(RGB32,x);
- LOAD(RGB32,s1+BPP(RGB32),x); /* [0,1] */
- r = GET_R(RGB32,x);
- b = GET_B(RGB32,x);
- y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b];
- d1[1] = yytab [y];
- d3[1] = GET_A(RGB32,x);
- LOAD(RGB32,s2,x); /* [1,0] */
- r2 = (r = GET_R(RGB32,x));
- b2 = (b = GET_B(RGB32,x));
- y2 = (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
- d2[0] = yytab [y];
- d4[0] = GET_A(RGB32,x);
- LOAD(RGB32,s2+BPP(RGB32),x); /* [1,1] */
- r2 += (r = GET_R(RGB32,x));
- b2 += (b = GET_B(RGB32,x));
- y2 += (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
- d2[1] = yytab [y];
- d4[1] = GET_A(RGB32,x);
- }
- /* average chromas: */
- dv[0] = vrytab [VMIN+(r2-y2)/2];
- du[0] = ubytab [UMIN+(b2-y2)/2];
- /* go to the next block: */
- s1 += 2 * BPP(RGB32); s2 += 2 * BPP(RGB32);
- d1 += 2; d2 += 2;
- d3 += 2; d4 += 2;
- du += 1; dv += 1;
- }
- /* switch to the next two lines: */
- s1 += src_pitch * 2 - dest_dx * BPP(RGB32);
- s2 += src_pitch * 2 - dest_dx * BPP(RGB32);
- d1 += dest_pitch * 2 - dest_dx;
- d2 += dest_pitch * 2 - dest_dx;
- d3 += dest_pitch * 2 - dest_dx;
- d4 += dest_pitch * 2 - dest_dx;
- du += (dest_pitch - dest_dx)/2;
- dv += (dest_pitch - dest_dx)/2;
- }
- break;
- case CRM_11_00:
- /* the main loop (processes 2 lines a time): */
- for (i = 0; i < dest_dy/2; i ++) {
- /* convert 2x2 block: */
- for (j = 0; j < dest_dx/2; j ++) {
- int r2, b2, y2;
- /* process lumas: */
- {
- PIXEL(RGB32,x);
- register unsigned int r, b, y;
- LOAD(RGB32,s1,x); /* [0,0] */
- r2 = (r = GET_R(RGB32,x));
- b2 = (b = GET_B(RGB32,x));
- y2 = (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
- d1[0] = yytab [y];
- d3[0] = GET_A(RGB32,x);
- LOAD(RGB32,s1+BPP(RGB32),x); /* [0,1] */
- r2 += (r = GET_R(RGB32,x));
- b2 += (b = GET_B(RGB32,x));
- y2 += (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
- d1[1] = yytab [y];
- d3[1] = GET_A(RGB32,x);
- LOAD(RGB32,s2,x); /* [1,0] */
- r = GET_R(RGB32,x);
- b = GET_B(RGB32,x);
- y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b];
- d2[0] = yytab [y];
- d4[0] = GET_A(RGB32,x);
- LOAD(RGB32,s2+BPP(RGB32),x); /* [1,1] */
- r = GET_R(RGB32,x);
- b = GET_B(RGB32,x);
- y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b];
- d2[1] = yytab [y];
- d4[1] = GET_A(RGB32,x);
- }
- /* average chromas: */
- dv[0] = vrytab [VMIN+(r2-y2)/2];
- du[0] = ubytab [UMIN+(b2-y2)/2];
- /* go to the next block: */
- s1 += 2 * BPP(RGB32); s2 += 2 * BPP(RGB32);
- d1 += 2; d2 += 2;
- d3 += 2; d4 += 2;
- du += 1; dv += 1;
- }
- /* switch to the next two lines: */
- s1 += src_pitch * 2 - dest_dx * BPP(RGB32);
- s2 += src_pitch * 2 - dest_dx * BPP(RGB32);
- d1 += dest_pitch * 2 - dest_dx;
- d2 += dest_pitch * 2 - dest_dx;
- d3 += dest_pitch * 2 - dest_dx;
- d4 += dest_pitch * 2 - dest_dx;
- du += (dest_pitch - dest_dx)/2;
- dv += (dest_pitch - dest_dx)/2;
- }
- break;
- case CRM_11_11:
- default:
- /* the main loop (processes 2 lines a time): */
- for (i = 0; i < dest_dy/2; i ++) {
- /* convert 2x2 block: */
- for (j = 0; j < dest_dx/2; j ++) {
- int r4, b4, y4;
- /* process lumas: */
- {
- PIXEL(RGB32,x);
- register unsigned int r, b, y;
- LOAD(RGB32,s1,x); /* [0,0] */
- r4 = (r = GET_R(RGB32,x));
- b4 = (b = GET_B(RGB32,x));
- y4 = (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
- d1[0] = yytab [y];
- d3[0] = GET_A(RGB32,x);
- LOAD(RGB32,s1+BPP(RGB32),x); /* [0,1] */
- r4 += (r = GET_R(RGB32,x));
- b4 += (b = GET_B(RGB32,x));
- y4 += (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
- d1[1] = yytab [y];
- d3[1] = GET_A(RGB32,x);
- LOAD(RGB32,s2,x); /* [1,0] */
- r4 += (r = GET_R(RGB32,x));
- b4 += (b = GET_B(RGB32,x));
- y4 += (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
- d2[0] = yytab [y];
- d4[0] = GET_A(RGB32,x);
- LOAD(RGB32,s2+BPP(RGB32),x); /* [1,1] */
- r4 += (r = GET_R(RGB32,x));
- b4 += (b = GET_B(RGB32,x));
- y4 += (y = yrtab [r] + ygtab [GET_G(RGB32,x)] + ybtab [b]);
- d2[1] = yytab [y];
- d4[1] = GET_A(RGB32,x);
- }
- /* average chromas: */
- dv[0] = vrytab [VMIN+(r4-y4)/4];
- du[0] = ubytab [UMIN+(b4-y4)/4];
- /* go to the next block: */
- s1 += 2 * BPP(RGB32); s2 += 2 * BPP(RGB32);
- d1 += 2; d2 += 2;
- d3 += 2; d4 += 2;
- du += 1; dv += 1;
- }
- /* switch to the next two lines: */
- s1 += src_pitch * 2 - dest_dx * BPP(RGB32);
- s2 += src_pitch * 2 - dest_dx * BPP(RGB32);
- d1 += dest_pitch * 2 - dest_dx;
- d2 += dest_pitch * 2 - dest_dx;
- d3 += dest_pitch * 2 - dest_dx;
- d4 += dest_pitch * 2 - dest_dx;
- du += (dest_pitch - dest_dx)/2;
- dv += (dest_pitch - dest_dx)/2;
- }
- }
- }
- /*
- * else {
- * put all the color-dependent stuff here ...
- * }
- */
- return 0;
- }
- /* rgb2yuv.c -- end of file */