2535 lines
79 KiB
C
2535 lines
79 KiB
C
/*
|
||
* @DEC_COPYRIGHT@
|
||
*/
|
||
/*
|
||
* HISTORY
|
||
* $Log: sc_convert.c,v $
|
||
* Revision 1.1.8.6 1996/10/28 17:32:17 Hans_Graves
|
||
* Add use IsYUV422Sep() macro in ScConvertSepYUVToOther().
|
||
* [1996/10/28 16:51:30 Hans_Graves]
|
||
*
|
||
* Revision 1.1.8.5 1996/10/02 18:42:50 Hans_Graves
|
||
* Fix RGB 24-bit conversion in ScYuv411ToRgb().
|
||
* [1996/10/02 18:32:51 Hans_Graves]
|
||
*
|
||
* Revision 1.1.8.4 1996/09/29 22:19:32 Hans_Graves
|
||
* Added stride support to ScYuv411ToRgb()
|
||
* [1996/09/29 21:27:17 Hans_Graves]
|
||
*
|
||
* Revision 1.1.8.3 1996/09/18 23:45:34 Hans_Graves
|
||
* Added ScConvert1611PlanarTo411_C, ScConvert411sTo422s_C, and ScRgbToYuv411
|
||
* [1996/09/18 21:52:27 Hans_Graves]
|
||
*
|
||
* Revision 1.1.8.2 1996/05/07 19:55:42 Hans_Graves
|
||
* Added YUV 4:1:1 to RGB 32-bit conversion - C code
|
||
* [1996/05/07 19:44:38 Hans_Graves]
|
||
*
|
||
* Revision 1.1.6.4 1996/04/11 20:21:57 Hans_Graves
|
||
* Moved ScIsUpsideDown() from sc_convert_yuv.c
|
||
* [1996/04/11 20:03:44 Hans_Graves]
|
||
*
|
||
* Revision 1.1.6.3 1996/04/09 16:04:24 Hans_Graves
|
||
* Added ValidateBI_BITFIELDS(). Fixed BI_RGB 16 bit conversion in ScYuv411ToRgb()
|
||
* [1996/04/09 14:46:27 Hans_Graves]
|
||
*
|
||
* Revision 1.1.6.2 1996/04/03 21:41:07 Hans_Graves
|
||
* Change include path for <mmsystems.h>
|
||
* [1996/04/03 21:37:55 Hans_Graves]
|
||
*
|
||
* Revision 1.1.4.4 1996/02/22 17:35:17 Bjorn_Engberg
|
||
* Added support for BI_BITFIELDS 16 and BI_RGB 32 rendering.
|
||
* [1996/02/22 17:31:35 Bjorn_Engberg]
|
||
*
|
||
* Revision 1.1.4.3 1996/01/02 18:30:33 Bjorn_Engberg
|
||
* Got rid of compiler warnings: Added Casts
|
||
* [1996/01/02 15:21:27 Bjorn_Engberg]
|
||
*
|
||
* Revision 1.1.4.2 1995/12/07 19:31:15 Hans_Graves
|
||
* Added ScConvert422PlanarTo411_C()
|
||
* [1995/12/07 17:44:00 Hans_Graves]
|
||
*
|
||
* Revision 1.1.2.21 1995/11/30 20:17:02 Hans_Graves
|
||
* Cleaned up ScYuv422toRgb() routine
|
||
* [1995/11/30 20:13:26 Hans_Graves]
|
||
*
|
||
* Revision 1.1.2.20 1995/11/28 22:47:28 Hans_Graves
|
||
* Make XIMAGE 24 identical to BI_BITFIELDS pBGR
|
||
* [1995/11/28 22:26:11 Hans_Graves]
|
||
*
|
||
* Added ScYuv1611ToRgb() routine for use by Indeo
|
||
* [1995/11/28 21:34:28 Hans_Graves]
|
||
*
|
||
* Revision 1.1.2.19 1995/11/17 21:31:21 Hans_Graves
|
||
* Add ScYuv411ToRgb() conversion routine.
|
||
* [1995/11/17 20:50:51 Hans_Graves]
|
||
*
|
||
* Revision 1.1.2.18 1995/10/25 18:19:18 Bjorn_Engberg
|
||
* Support Upside Down in ScRgbInterlToYuvInterl().
|
||
* [1995/10/25 18:05:18 Bjorn_Engberg]
|
||
*
|
||
* Revision 1.1.2.17 1995/10/10 21:43:02 Bjorn_Engberg
|
||
* Speeded up RgbToYuv code and made it table driven.
|
||
* [1995/10/10 21:21:48 Bjorn_Engberg]
|
||
*
|
||
* Revision 1.1.2.16 1995/10/09 19:44:31 Bjorn_Engberg
|
||
* Removed ValidateBI_BITFIELDS(), it's now in sc_convert_yuv.c
|
||
* [1995/10/09 19:44:14 Bjorn_Engberg]
|
||
*
|
||
* Revision 1.1.2.15 1995/10/06 20:43:23 Farokh_Morshed
|
||
* Enhance ScRgbInterlToYuvInterl to handle BI_BITFIELDS
|
||
* [1995/10/06 20:42:43 Farokh_Morshed]
|
||
*
|
||
* Revision 1.1.2.14 1995/10/02 19:30:26 Bjorn_Engberg
|
||
* Added support for Assebler YUV to RGB routines.
|
||
* [1995/10/02 18:39:05 Bjorn_Engberg]
|
||
*
|
||
* Revision 1.1.2.13 1995/09/28 20:37:53 Farokh_Morshed
|
||
* Handle negative Height
|
||
* [1995/09/28 20:37:39 Farokh_Morshed]
|
||
*
|
||
* Revision 1.1.2.12 1995/09/26 15:58:47 Paul_Gauthier
|
||
* Fix mono JPEG to interlaced 422 YUV conversion
|
||
* [1995/09/26 15:58:09 Paul_Gauthier]
|
||
*
|
||
* Revision 1.1.2.11 1995/09/22 18:56:35 Paul_Gauthier
|
||
* {** Merge Information **}
|
||
* {** Command used: bsubmit **}
|
||
* {** Ancestor revision: 1.1.2.7 **}
|
||
* {** Merge revision: 1.1.2.10 **}
|
||
* {** End **}
|
||
* Use faster method for 16bit YUV output for TGA2
|
||
* [1995/09/22 18:39:55 Paul_Gauthier]
|
||
*
|
||
* Revision 1.1.2.10 1995/09/21 18:26:45 Farokh_Morshed
|
||
* When BI_RGB or BI_BITFIELDS, invert the image while translating from
|
||
* YUV to RGB. Also fix the coefficient for the YUV colors.
|
||
* This work was actually done by Bjorn
|
||
* [1995/09/21 18:26:19 Farokh_Morshed]
|
||
*
|
||
* Revision 1.1.2.9 1995/09/20 17:39:18 Karen_Dintino
|
||
* Add RGB support to JPEG
|
||
* [1995/09/20 17:37:22 Karen_Dintino]
|
||
*
|
||
* Revision 1.1.2.8 1995/09/20 14:59:31 Bjorn_Engberg
|
||
* Port to NT
|
||
* [1995/09/20 14:41:10 Bjorn_Engberg]
|
||
*
|
||
* Revision 1.1.2.7 1995/09/18 19:47:47 Paul_Gauthier
|
||
* Added conversion of MPEG planar 4:1:1 to interleaved 4:2:2
|
||
* [1995/09/18 19:46:13 Paul_Gauthier]
|
||
*
|
||
* Revision 1.1.2.6 1995/09/14 14:40:34 Karen_Dintino
|
||
* Move RgbToYuv out of rendition
|
||
* [1995/09/14 14:26:13 Karen_Dintino]
|
||
*
|
||
* Revision 1.1.2.5 1995/09/11 18:47:25 Farokh_Morshed
|
||
* {** Merge Information **}
|
||
* {** Command used: bsubmit **}
|
||
* {** Ancestor revision: 1.1.2.3 **}
|
||
* {** Merge revision: 1.1.2.4 **}
|
||
* {** End **}
|
||
* Support BI_BITFIELDS format
|
||
* [1995/09/11 18:43:39 Farokh_Morshed]
|
||
*
|
||
* Revision 1.1.2.4 1995/09/05 17:17:34 Paul_Gauthier
|
||
* Fix for softjpeg decompression JPEG -> BICOMP_DECYUVDIB
|
||
* [1995/09/05 17:17:09 Paul_Gauthier]
|
||
*
|
||
* Revision 1.1.2.3 1995/08/03 15:01:06 Hans_Graves
|
||
* Moved ScConvert422ToYUV_char_C() from h261.
|
||
* [1995/08/03 14:46:23 Hans_Graves]
|
||
*
|
||
* Revision 1.1.2.2 1995/05/31 18:07:27 Hans_Graves
|
||
* Inclusion in new SLIB location.
|
||
* [1995/05/31 16:06:30 Hans_Graves]
|
||
*
|
||
* $EndLog$
|
||
*/
|
||
|
||
/*****************************************************************************
|
||
** Copyright (c) Digital Equipment Corporation, 1993 **
|
||
** **
|
||
** All Rights Reserved. Unpublished rights reserved under the copyright **
|
||
** laws of the United States. **
|
||
** **
|
||
** The software contained on this media is proprietary to and embodies **
|
||
** the confidential technology of Digital Equipment Corporation. **
|
||
** Possession, use, duplication or dissemination of the software and **
|
||
** media is authorized only pursuant to a valid written license from **
|
||
** Digital Equipment Corporation. **
|
||
** **
|
||
** RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure by the U.S. **
|
||
** Government is subject to restrictions as set forth in Subparagraph **
|
||
** (c)(1)(ii) of DFARS 252.227-7013, or in FAR 52.227-19, as applicable. **
|
||
******************************************************************************/
|
||
|
||
/*
|
||
**
|
||
** Miscellaneous conversion utility subroutines
|
||
**
|
||
** Author(s): Victor Bahl
|
||
** Date: May 27, 1993
|
||
**
|
||
*/
|
||
|
||
#include <stdio.h> /* NULL */
|
||
#include <sys/types.h>
|
||
#ifdef WIN32
|
||
#include <windows.h>
|
||
#include <mmsystem.h>
|
||
#else /* !WIN32 */
|
||
#include <mmsystem.h>
|
||
#endif /* !WIN32 */
|
||
|
||
#include "SC_conv.h"
|
||
#include "SC_err.h"
|
||
|
||
#ifndef BI_DECSEPRGBDIB
|
||
#define BI_DECSEPRGBDIB mmioFOURCC('D','S','R','G')
|
||
#endif
|
||
|
||
#define NEW_YCBCR /* Use new YUV to RGB coefficients */
|
||
|
||
/*
|
||
** Name: ScCreateBMHeader
|
||
** Purpose: Allocate memory for a (Microsoft specified) bitmap header and
|
||
** fill in the appropriate fields
|
||
**
|
||
*/
|
||
BITMAPINFOHEADER *ScCreateBMHeader(int width, int height, int bpp,
|
||
int format, int ncolors)
|
||
{
|
||
BITMAPINFOHEADER *pHead;
|
||
int struct_size = sizeof(BITMAPINFOHEADER) + ncolors*sizeof(RGBQUAD);
|
||
|
||
if ((pHead = (BITMAPINFOHEADER *)ScAlloc(struct_size)) == NULL) {
|
||
puts("Can't Allocate memory for image headers");
|
||
return NULL;
|
||
}
|
||
|
||
pHead->biSize = sizeof(BITMAPINFOHEADER);
|
||
pHead->biWidth = width;
|
||
pHead->biHeight = height;
|
||
pHead->biPlanes = 1;
|
||
pHead->biBitCount = (WORD)bpp;
|
||
pHead->biCompression = format;
|
||
pHead->biSizeImage = 0;
|
||
pHead->biXPelsPerMeter = 0;
|
||
pHead->biYPelsPerMeter = 0;
|
||
pHead->biClrUsed = ncolors;
|
||
pHead->biClrImportant = 0;
|
||
|
||
return pHead;
|
||
}
|
||
|
||
/*
|
||
** Function: ScIsUpsideDown
|
||
** Descript: Return TRUE if the current combination
|
||
** of input and output formats and image
|
||
** heights means that the image should be
|
||
** flipped during the render stage.
|
||
*/
|
||
int ScIsUpsideDown( BITMAPINFOHEADER *lpbiIn,
|
||
BITMAPINFOHEADER *lpbiOut )
|
||
{
|
||
int ups = 0 ;
|
||
if( lpbiIn )
|
||
ups = (((lpbiIn->biCompression == BI_RGB) ||
|
||
(lpbiIn->biCompression == BI_BITFIELDS)) ^
|
||
((int) lpbiIn->biHeight < 0)) ;
|
||
if( lpbiOut )
|
||
ups ^= (((lpbiOut->biCompression == BI_RGB) ||
|
||
(lpbiOut->biCompression == BI_BITFIELDS)) ^
|
||
((int) lpbiOut->biHeight < 0)) ;
|
||
return ups ;
|
||
}
|
||
|
||
/*
|
||
**++
|
||
** FUNCTIONAL_DESCRIPTION:
|
||
** Return an enum value that validates a BI_BITFIELDS bitmapinfoheader
|
||
** with BI_BITFIELDS format.
|
||
**
|
||
** FORMAL PARAMETERS:
|
||
** Pointer to bitmapinfoheader
|
||
** RETURN VALUE:
|
||
** A value from enum type ValidBI_BITFIELDSKinds.
|
||
**/
|
||
enum ValidBI_BITFIELDSKinds ValidateBI_BITFIELDS(
|
||
LPBITMAPINFOHEADER lpbi)
|
||
{
|
||
DWORD *MaskPtr;
|
||
|
||
if (lpbi == NULL || lpbi->biCompression != BI_BITFIELDS)
|
||
return InvalidBI_BITFIELDS;
|
||
|
||
MaskPtr = (DWORD *)&lpbi[1];
|
||
|
||
/*
|
||
* For 32-bit BI_BITFIELDS, we support
|
||
* only the special cases 00RRGGBB and 00BBGGRR.
|
||
*/
|
||
|
||
if( lpbi->biBitCount == 32 ) {
|
||
if (MaskPtr[1] != 0x0000FF00U)
|
||
return InvalidBI_BITFIELDS;
|
||
else if (MaskPtr[0] == 0x00FF0000U && MaskPtr[2] == 0x000000FFU)
|
||
return pRGB;
|
||
else if (MaskPtr[0] == 0x000000FFU && MaskPtr[2] == 0x00FF0000U)
|
||
return pBGR;
|
||
else
|
||
return InvalidBI_BITFIELDS;
|
||
}
|
||
|
||
#ifdef WIN32
|
||
/*
|
||
* For 16-bit BI_BITFIELDS, we support any legal
|
||
* color arrangement, but RGB565 and RGB555 are
|
||
* recognized as special since we have extra
|
||
* fast assembler code for those cases.
|
||
*/
|
||
|
||
else if( lpbi->biBitCount == 16 ) {
|
||
int i ;
|
||
if( MaskPtr[2] == 0x001f ) {
|
||
if( MaskPtr[0] == 0xf800 && MaskPtr[1] == 0x07e0 )
|
||
return pRGB565 ;
|
||
else if( MaskPtr[0] == 0x7c00 && MaskPtr[1] == 0x03e00 )
|
||
return pRGB555 ;
|
||
}
|
||
/*
|
||
* Generic case: First make sure that each mask is
|
||
* a 16-bit mask.
|
||
*/
|
||
|
||
if( (MaskPtr[0] | MaskPtr[1] | MaskPtr[2]) & ~0x0000ffff )
|
||
return InvalidBI_BITFIELDS ;
|
||
|
||
/*
|
||
* Masks must not overlap.
|
||
*/
|
||
|
||
if( (MaskPtr[0] & MaskPtr[1]) ||
|
||
(MaskPtr[0] & MaskPtr[2]) ||
|
||
(MaskPtr[1] & MaskPtr[2]) )
|
||
return InvalidBI_BITFIELDS ;
|
||
|
||
/*
|
||
* Make sure each mask contains a contiguous
|
||
* sequence of 1's (or is 0).
|
||
*/
|
||
|
||
for( i=0 ; i<3 ; i++ ) {
|
||
DWORD v = MaskPtr[i] ;
|
||
if( (((v-1)|v)+1)&v )
|
||
return InvalidBI_BITFIELDS ;
|
||
}
|
||
|
||
/*
|
||
* If we pass all these tests, we have
|
||
* a valid generic 16-bit BI_BITFIELDS case.
|
||
*/
|
||
|
||
return pRGBnnn ;
|
||
}
|
||
|
||
#endif /* WIN32 */
|
||
|
||
/*
|
||
* No other biBitCounts are supported.
|
||
*/
|
||
|
||
return InvalidBI_BITFIELDS ;
|
||
}
|
||
|
||
/*********************** Conversion Routines ***************************/
|
||
|
||
static void sc_ExtractBlockNonInt(u_char *InData, float **OutData,
|
||
int ByteWidth, int x, int y)
|
||
{
|
||
register int i,j;
|
||
u_char *Inp, *IStart = InData + 8*y*ByteWidth + 8*x;
|
||
|
||
for (i = 0 , Inp = IStart ; i < 8 ; i++ , Inp += ByteWidth)
|
||
for (j = 0 ; j < 8 ; j++)
|
||
*((*OutData)++) = (float)((int)(*Inp++) - 128);
|
||
}
|
||
|
||
|
||
/*
|
||
** Name: ScConvertSepYUVToOther
|
||
** Purpose: Convert Seperated YUV 422 to another format
|
||
**
|
||
*/
|
||
ScStatus_t ScConvertSepYUVToOther(BITMAPINFOHEADER *InBmh,
|
||
BITMAPINFOHEADER *OutBmh,
|
||
u_char *OutImage,
|
||
u_char *YData, u_char *CbData, u_char *CrData)
|
||
{
|
||
/*
|
||
** no need to do extensive checking, DecompressBegin and CompressBegin
|
||
** should take care of static checking (eg. valid output colorspace
|
||
*/
|
||
|
||
|
||
/*
|
||
** Are we converting from SepYUV to RGB ?
|
||
*/
|
||
if ((OutBmh->biCompression == BI_RGB) ||
|
||
(OutBmh->biCompression == BI_BITFIELDS) ||
|
||
(OutBmh->biCompression == BI_DECXIMAGEDIB) ||
|
||
(OutBmh->biCompression == BI_DECSEPRGBDIB)) {
|
||
/*
|
||
** It is assumed that YUV is subsampled 4:2:2, we will need to
|
||
** generalize the code below to handle other cases as well -- VB
|
||
*/
|
||
if (InBmh->biBitCount == 8)
|
||
ScYuv422ToRgb (OutBmh, YData, NULL, NULL, OutImage);
|
||
else
|
||
ScYuv422ToRgb (OutBmh, YData, CbData, CrData, OutImage);
|
||
}
|
||
/*
|
||
** Are we converting from SepYUV to Interlaced YUV ?
|
||
*/
|
||
else if (IsYUV422Sep(OutBmh->biCompression))
|
||
{
|
||
/*
|
||
** It is assumed that YUV is subsampled 4:2:2, we will need to
|
||
** generalize the code below to handle other cases as well
|
||
** XXX - Bad idea to do this here, should be done as part of
|
||
** decompression (VB)
|
||
** XXX - While we can move the Sep YUV to 422 interleaved
|
||
** to decompression, we also need a copy here so we
|
||
** can use this as a general purpose dither'ing
|
||
** device. (JPL)
|
||
*/
|
||
int i, j;
|
||
|
||
/*
|
||
** If the input format is Mono JPEG and the output format is
|
||
** packed YUV422, we must reset the U and V values to neutral (Gray).
|
||
*/
|
||
if (InBmh->biBitCount == 8) {
|
||
#ifdef __alpha
|
||
/*
|
||
* If we're an Alpha, and the buffer is quadword
|
||
* aligned, we can use 64-bit transfers.
|
||
*/
|
||
if( ((INT_PTR) OutImage & 0x7) == 0 )
|
||
{
|
||
_int64 val = 0x7f007f007f007f00L ;
|
||
_int64 *iptr = (_int64 *) OutImage ;
|
||
for( i=(OutBmh->biWidth*abs(OutBmh->biHeight)>>2) ; i>0 ; i-- )
|
||
*iptr++ = val ;
|
||
}
|
||
else
|
||
#endif /* __alpha */
|
||
{
|
||
int val = 0x7f007f00 ;
|
||
int *iptr = (int *) OutImage ;
|
||
for( i=(OutBmh->biWidth*abs(OutBmh->biHeight)>>1) ; i>0 ; i-- )
|
||
*iptr++ = val ;
|
||
}
|
||
/*
|
||
** Plug in the luminance samples
|
||
*/
|
||
for( i=(OutBmh->biWidth * abs(OutBmh->biHeight)) ; i>0 ; i-- ) {
|
||
*OutImage = *YData++;
|
||
OutImage +=2;
|
||
}
|
||
}
|
||
/*
|
||
** Color input
|
||
*/
|
||
else {
|
||
/* If this is quad padded in both X and Y and quad aligned,
|
||
** we can call the assembly routine
|
||
*/
|
||
if ( (abs(OutBmh->biHeight) & 0x7) == 0 &&
|
||
(OutBmh->biWidth & 0x7) == 0 &&
|
||
((ULONG_PTR)OutImage & 0xf) == 0 )
|
||
{
|
||
ScConvert422PlanarTo422i(YData, CbData, CrData, OutImage,
|
||
OutBmh->biWidth, abs(OutBmh->biHeight));
|
||
}
|
||
else {
|
||
for (i=0; i<abs(OutBmh->biHeight); i++)
|
||
/* Remember, pixels are 16 bit in interleaved YUV. That
|
||
** means the 4 bytes below represent two pixels so our
|
||
** loop should be for half the width.
|
||
*/
|
||
for (j=0; j<OutBmh->biWidth>>1; j++) { /* Note: was j+=2 */
|
||
*OutImage++ = *YData++;
|
||
*OutImage++ = *CbData++;
|
||
*OutImage++ = *YData++;
|
||
*OutImage++ = *CrData++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else return(ScErrorUnrecognizedFormat);
|
||
|
||
return(ScErrorNone);
|
||
}
|
||
|
||
/*
|
||
** Name: ScYuv411ToRgb
|
||
** Purpose: convert 16-bit YCrCb 4:1:1 to an 16/24/32-bit RGB
|
||
**
|
||
** Note: The code below is pixel based and is inefficient, we
|
||
** plan to replace faster assembly code
|
||
*/
|
||
ScStatus_t ScYuv411ToRgb (BITMAPINFOHEADER *Bmh, u_char *Y, u_char *Cb,
|
||
u_char *Cr, u_char *ImageOut, int Width, int Height, long stride)
|
||
{
|
||
const int pixels = Width;
|
||
int lines = Height;
|
||
register int row, col;
|
||
register int Luma, U, V;
|
||
/* Variables to hold R, G and B values for a 2x2 matrix of pixels */
|
||
int R1,R2,R3,R4;
|
||
int G1,G2,G3,G4;
|
||
int B1,B2,B3,B4;
|
||
int Ups = 0, tmp; /* Flip image upside down */
|
||
u_char *Y1=Y, *Y2=Y+pixels;
|
||
#define _LoadRGBfrom411() \
|
||
R1 = R2 = R3 = R4 = (int) ( + (1.596 * V)); \
|
||
G1 = G2 = G3 = G4 = (int) (- (0.391 * U) - (0.813 * V)); \
|
||
B1 = B2 = B3 = B4 = (int) (+ (2.018 * U) ); \
|
||
Luma = (int) (((int) *(Y1++) - 16) * 1.164); \
|
||
R1 += Luma; G1 +=Luma; B1 += Luma; \
|
||
Luma = (int) (((int) *(Y1++) - 16) * 1.164); \
|
||
R2 += Luma; G2 +=Luma; B2 += Luma; \
|
||
if ((R1 | G1 | B1 | R2 | G2 | B2) & 0xffffff00) { \
|
||
if (R1<0) R1=0; else if (R1>255) R1=255; \
|
||
if (G1<0) G1=0; else if (G1>255) G1=255; \
|
||
if (B1<0) B1=0; else if (B1>255) B1=255; \
|
||
if (R2<0) R2=0; else if (R2>255) R2=255; \
|
||
if (G2<0) G2=0; else if (G2>255) G2=255; \
|
||
if (B2<0) B2=0; else if (B2>255) B2=255; \
|
||
} \
|
||
Luma = (int) (((int) *(Y2++) - 16) * 1.164); \
|
||
R3 += Luma; G3 +=Luma; B3 += Luma; \
|
||
Luma = (int) (((int) *(Y2++) - 16) * 1.164); \
|
||
R4 += Luma; G4 +=Luma; B4 += Luma; \
|
||
if ((R3 | G3 | B3 | R4 | G4 | B4) & 0xffffff00) { \
|
||
if (R3<0) R3=0; else if (R3>255) R3=255; \
|
||
if (G3<0) G3=0; else if (G3>255) G3=255; \
|
||
if (B3<0) B3=0; else if (B3>255) B3=255; \
|
||
if (R4<0) R4=0; else if (R4>255) R4=255; \
|
||
if (G4<0) G4=0; else if (G4>255) G4=255; \
|
||
if (B4<0) B4=0; else if (B4>255) B4=255; \
|
||
}
|
||
|
||
/*
|
||
* Normally, images are stored right side up, that is with the
|
||
* first pixel in the buffer corresponding to the top left pixel
|
||
* in the image.
|
||
*
|
||
* The Microsoft standard Device Independent bitmap formats BI_RGB and
|
||
* BI_BITFIELD are stored with the lower left pixel first. We view that
|
||
* as upside down.
|
||
*
|
||
* Each format can also have a negative height, which also signifes
|
||
* upside down.
|
||
*
|
||
* Since two negatives makes a positive, that means that BI_ formats with
|
||
* negative height are right side up.
|
||
*/
|
||
if( Bmh->biCompression == BI_RGB ||
|
||
Bmh->biCompression == BI_BITFIELDS )
|
||
Ups = 1 ;
|
||
|
||
if( lines < 0 ) {
|
||
Ups = 1-Ups ;
|
||
lines = -lines ;
|
||
}
|
||
|
||
/*
|
||
** The assumption is that YCrCb are subsampled 4:1:1
|
||
** YSize = lines * pixels
|
||
** CbSize = CrSize = (lines*pixels)/4
|
||
*/
|
||
switch (Bmh->biCompression)
|
||
{
|
||
case BI_RGB:
|
||
switch (Bmh->biBitCount)
|
||
{
|
||
case 15:
|
||
{
|
||
u_short *Sout1 = (u_short *)ImageOut, *Sout2=Sout1+pixels;
|
||
for (row = 0; row < lines; row+=2)
|
||
{
|
||
if (Ups)
|
||
{
|
||
tmp = stride * (lines-row-1) ;
|
||
Sout1 = (u_short *)ImageOut+tmp; /* For 16-bit */
|
||
Sout2=Sout1-stride;
|
||
}
|
||
else
|
||
{
|
||
tmp = stride * row;
|
||
Sout1 = (u_short *)ImageOut+tmp; /* For 16-bit */
|
||
Sout2=Sout1+stride;
|
||
}
|
||
Y2=Y1+pixels;
|
||
for (col = 0; col < pixels; col += 2)
|
||
{
|
||
U = *Cb++ - 128;
|
||
V = *Cr++ - 128;
|
||
_LoadRGBfrom411();
|
||
*(Sout1++) = ((R1&0xf8)<<7)|((G1&0xf8)<<2)|((B1&0xf8)>>3);
|
||
*(Sout1++) = ((R2&0xf8)<<7)|((G2&0xf8)<<2)|((B2&0xf8)>>3);
|
||
*(Sout2++) = ((R3&0xf8)<<7)|((G3&0xf8)<<2)|((B3&0xf8)>>3);
|
||
*(Sout2++) = ((R4&0xf8)<<7)|((G4&0xf8)<<2)|((B4&0xf8)>>3);
|
||
}
|
||
Y1=Y2;
|
||
}
|
||
}
|
||
break;
|
||
case 16:
|
||
{
|
||
u_short *Sout1 = (u_short *)ImageOut, *Sout2=Sout1+pixels;
|
||
for (row = 0; row < lines; row+=2)
|
||
{
|
||
if (Ups)
|
||
{
|
||
tmp = stride * (lines-row-1) ;
|
||
Sout1 = (u_short *)ImageOut+tmp; /* For 16-bit */
|
||
Sout2=Sout1-stride;
|
||
}
|
||
else
|
||
{
|
||
tmp = stride * row;
|
||
Sout1 = (u_short *)ImageOut+tmp; /* For 16-bit */
|
||
Sout2=Sout1+stride;
|
||
}
|
||
Y2=Y1+pixels;
|
||
for (col = 0; col < pixels; col += 2)
|
||
{
|
||
U = *Cb++ - 128;
|
||
V = *Cr++ - 128;
|
||
_LoadRGBfrom411();
|
||
#ifdef WIN95 /* RGB 565 - 16 bit */
|
||
*(Sout1++) = ((R1&0xf8)<<8)|((G1&0xfC)<<3)|((B1&0xf8)>>3);
|
||
*(Sout1++) = ((R2&0xf8)<<8)|((G2&0xfC)<<3)|((B2&0xf8)>>3);
|
||
*(Sout2++) = ((R3&0xf8)<<8)|((G3&0xfC)<<3)|((B3&0xf8)>>3);
|
||
*(Sout2++) = ((R4&0xf8)<<8)|((G4&0xfC)<<3)|((B4&0xf8)>>3);
|
||
#else /* RGB 555 - 15 bit */
|
||
*(Sout1++) = ((R1&0xf8)<<7)|((G1&0xf8)<<2)|((B1&0xf8)>>3);
|
||
*(Sout1++) = ((R2&0xf8)<<7)|((G2&0xf8)<<2)|((B2&0xf8)>>3);
|
||
*(Sout2++) = ((R3&0xf8)<<7)|((G3&0xf8)<<2)|((B3&0xf8)>>3);
|
||
*(Sout2++) = ((R4&0xf8)<<7)|((G4&0xf8)<<2)|((B4&0xf8)>>3);
|
||
#endif
|
||
}
|
||
Y1=Y2;
|
||
}
|
||
}
|
||
break;
|
||
case 24:
|
||
{
|
||
u_char *Cout1, *Cout2;
|
||
stride*=3;
|
||
for (row = 0; row < lines; row+=2)
|
||
{
|
||
if (Ups)
|
||
{
|
||
tmp = stride * (lines-row-1) ;
|
||
Cout1 = (u_char *)(ImageOut + tmp); /* For 24-bit */
|
||
Cout2=Cout1-stride;
|
||
}
|
||
else
|
||
{
|
||
tmp = stride * row;
|
||
Cout1 = (u_char *)(ImageOut + tmp); /* For 24-bit */
|
||
Cout2=Cout1+stride;
|
||
}
|
||
Y2=Y1+pixels;
|
||
for (col = 0; col < pixels; col += 2)
|
||
{
|
||
U = *Cb++ - 128;
|
||
V = *Cr++ - 128;
|
||
_LoadRGBfrom411();
|
||
*(Cout1++) = (u_char)B1; *(Cout1++) = (u_char)G1; *(Cout1++) = (u_char)R1;
|
||
*(Cout1++) = (u_char)B2; *(Cout1++) = (u_char)G2; *(Cout1++) = (u_char)R2;
|
||
*(Cout2++) = (u_char)B3; *(Cout2++) = (u_char)G3; *(Cout2++) = (u_char)R3;
|
||
*(Cout2++) = (u_char)B4; *(Cout2++) = (u_char)G4; *(Cout2++) = (u_char)R4;
|
||
}
|
||
Y1=Y2;
|
||
}
|
||
}
|
||
break;
|
||
case 32:
|
||
{
|
||
unsigned dword *Wout1 = (unsigned dword *)ImageOut,
|
||
*Wout2=Wout1+pixels;
|
||
for (row = 0; row < lines; row+=2)
|
||
{
|
||
if (Ups)
|
||
{
|
||
tmp = stride * (lines-row-1);
|
||
Wout1 = (unsigned dword *)ImageOut + tmp;
|
||
Wout2=Wout1-stride;
|
||
}
|
||
else
|
||
{
|
||
tmp = stride * row;
|
||
Wout1 = (unsigned dword *)ImageOut + tmp;
|
||
Wout2=Wout1+stride;
|
||
}
|
||
Y2=Y1+pixels;
|
||
for (col = 0; col < pixels; col += 2)
|
||
{
|
||
U = *Cb++ - 128;
|
||
V = *Cr++ - 128;
|
||
_LoadRGBfrom411();
|
||
*(Wout1++) = (R1<<16) | (G1<<8) | B1;
|
||
*(Wout1++) = (R2<<16) | (G2<<8) | B2;
|
||
*(Wout2++) = (R3<<16) | (G3<<8) | B3;
|
||
*(Wout2++) = (R4<<16) | (G4<<8) | B4;
|
||
}
|
||
Y1=Y2;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
break;
|
||
case BI_DECSEPRGBDIB: /* 24-bit separate RGB */
|
||
{
|
||
u_char *RData1, *GData1, *BData1;
|
||
u_char *RData2, *GData2, *BData2;
|
||
RData1 = ImageOut;
|
||
GData1 = RData1 + (pixels * lines);
|
||
BData1 = GData1 + (pixels * lines);
|
||
RData2 = RData1 + pixels;
|
||
GData2 = GData1 + pixels;
|
||
BData2 = BData1 + pixels;
|
||
for (row = 0; row < lines; row+=2)
|
||
{
|
||
Y2=Y1+pixels;
|
||
for (col = 0; col < pixels; col += 2)
|
||
{
|
||
U = *Cb++ - 128;
|
||
V = *Cr++ - 128;
|
||
_LoadRGBfrom411();
|
||
*(RData1++) = (u_char)R1; *(RData1++) = (u_char)R2;
|
||
*(RData2++) = (u_char)R3; *(RData2++) = (u_char)R4;
|
||
*(GData1++) = (u_char)G1; *(GData1++) = (u_char)G2;
|
||
*(GData2++) = (u_char)G3; *(GData2++) = (u_char)G4;
|
||
*(BData1++) = (u_char)B1; *(BData1++) = (u_char)B2;
|
||
*(BData2++) = (u_char)B3; *(BData2++) = (u_char)B4;
|
||
}
|
||
RData1=RData2;
|
||
RData2=RData1+pixels;
|
||
Y1=Y2;
|
||
}
|
||
}
|
||
break;
|
||
case BI_DECXIMAGEDIB: /* XIMAGE 24 == pBGR */
|
||
case BI_BITFIELDS: /* 32-bit RGB */
|
||
{
|
||
unsigned dword *Iout1 = (unsigned dword *)ImageOut,
|
||
*Iout2=Iout1+pixels;
|
||
if (ValidateBI_BITFIELDS(Bmh) == pRGB)
|
||
for (row = 0; row < lines; row+=2)
|
||
{
|
||
if (Ups)
|
||
{
|
||
tmp = stride * (lines-row-1);
|
||
Iout1 = (unsigned dword *)ImageOut+tmp; /* For 32-bit */
|
||
Iout2=Iout1-stride;
|
||
}
|
||
else
|
||
{
|
||
tmp = stride * row;
|
||
Iout1 = (unsigned dword *)ImageOut+tmp; /* For 32-bit */
|
||
Iout2=Iout1+stride;
|
||
}
|
||
Y2=Y1+pixels;
|
||
for (col = 0; col < pixels; col += 2)
|
||
{
|
||
U = *Cb++ - 128;
|
||
V = *Cr++ - 128;
|
||
_LoadRGBfrom411();
|
||
*(Iout1++) = (R1<<16) | (G1<<8) | B1;
|
||
*(Iout1++) = (R2<<16) | (G2<<8) | B2;
|
||
*(Iout2++) = (R3<<16) | (G3<<8) | B3;
|
||
*(Iout2++) = (R4<<16) | (G4<<8) | B4;
|
||
}
|
||
Y1=Y2;
|
||
}
|
||
else /* pBGR and XIMAGE 24-bit */
|
||
for (row = 0; row < lines; row+=2)
|
||
{
|
||
if (Ups)
|
||
{
|
||
tmp = stride * (lines-row-1);
|
||
Iout1 = (unsigned dword *)ImageOut+tmp; /* For 32-bit */
|
||
Iout2=Iout1-stride;
|
||
}
|
||
else
|
||
{
|
||
tmp = stride * row;
|
||
Iout1 = (unsigned dword *)ImageOut+tmp; /* For 32-bit */
|
||
Iout2=Iout1+stride;
|
||
}
|
||
Y2=Y1+pixels;
|
||
for (col = 0; col < pixels; col += 2)
|
||
{
|
||
U = *Cb++ - 128;
|
||
V = *Cr++ - 128;
|
||
_LoadRGBfrom411();
|
||
*(Iout1++) = (B1<<16) | (G1<<8) | R1;
|
||
*(Iout1++) = (B2<<16) | (G2<<8) | R2;
|
||
*(Iout2++) = (B3<<16) | (G3<<8) | R3;
|
||
*(Iout2++) = (B4<<16) | (G4<<8) | R4;
|
||
}
|
||
Y1=Y2;
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
return(ScErrorUnrecognizedFormat);
|
||
}
|
||
return (NoErrors);
|
||
}
|
||
|
||
|
||
/*
|
||
** Name: ScYuv1611ToRgb
|
||
** Purpose: convert 16-bit YCrCb 16:1:1 (YUV9/YVU9) to 16/24/32-bit RGB
|
||
**
|
||
** Note: The code below is pixel based and is inefficient, we
|
||
** plan to replace faster assembly code
|
||
** This routine is used by Indeo, which actually only has 7-bits for
|
||
** Y, U and V components. The 8th bits are ignored.
|
||
*/
|
||
ScStatus_t ScYuv1611ToRgb (BITMAPINFOHEADER *Bmh, u_char *Y, u_char *Cb,
|
||
u_char *Cr, u_char *ImageOut)
|
||
{
|
||
const int pixels = Bmh->biWidth;
|
||
int lines = Bmh->biHeight;
|
||
register int row, col, i;
|
||
register int Luma, U, V;
|
||
/* Variables to hold R, G and B values for a 4x4 matrix of pixels */
|
||
int R[16], G[16], B[16], tmpR, tmpG, tmpB, cR, cG, cB;
|
||
int Ups = 0, tmp; /* Flip image upside down */
|
||
u_char *Y0=Y, *Y1, *Y2, *Y3;
|
||
#define _LoadRGBfrom1611() \
|
||
cR=(int) ( + (1.596 * V));\
|
||
cG=(int) (-(0.391 * U) - (0.813 * V));\
|
||
cB=(int) (+(2.018 * U) );\
|
||
for (i=0; i<4; i++) { \
|
||
Luma = (int) ((((int)(*Y0++)<<1) - 16) * 1.164); \
|
||
tmpR=cR + Luma; tmpG=cG + Luma; tmpB=cB + Luma; \
|
||
if ((tmpR | tmpG | tmpB) & 0xffffff00) { \
|
||
if (tmpR<0) R[i]=0; else if (tmpR>255) R[i]=255; else R[i]=tmpR; \
|
||
if (tmpG<0) G[i]=0; else if (tmpG>255) G[i]=255; else G[i]=tmpG; \
|
||
if (tmpB<0) B[i]=0; else if (tmpB>255) B[i]=255; else B[i]=tmpB; \
|
||
} else { R[i]=tmpR; G[i]=tmpG; B[i]=tmpB; } \
|
||
} \
|
||
for (; i<8; i++) { \
|
||
Luma = (int) ((((int)(*Y1++)<<1) - 16) * 1.164); \
|
||
tmpR=cR + Luma; tmpG=cG + Luma; tmpB=cB + Luma; \
|
||
if ((tmpR | tmpG | tmpB) & 0xffffff00) { \
|
||
if (tmpR<0) R[i]=0; else if (tmpR>255) R[i]=255; else R[i]=tmpR; \
|
||
if (tmpG<0) G[i]=0; else if (tmpG>255) G[i]=255; else G[i]=tmpG; \
|
||
if (tmpB<0) B[i]=0; else if (tmpB>255) B[i]=255; else B[i]=tmpB; \
|
||
} else { R[i]=tmpR; G[i]=tmpG; B[i]=tmpB; } \
|
||
} \
|
||
for (; i<12; i++) { \
|
||
Luma = (int) ((((int)(*Y2++)<<1) - 16) * 1.164); \
|
||
tmpR=cR + Luma; tmpG=cG + Luma; tmpB=cB + Luma; \
|
||
if ((tmpR | tmpG | tmpB) & 0xffffff00) { \
|
||
if (tmpR<0) R[i]=0; else if (tmpR>255) R[i]=255; else R[i]=tmpR; \
|
||
if (tmpG<0) G[i]=0; else if (tmpG>255) G[i]=255; else G[i]=tmpG; \
|
||
if (tmpB<0) B[i]=0; else if (tmpB>255) B[i]=255; else B[i]=tmpB; \
|
||
} else { R[i]=tmpR; G[i]=tmpG; B[i]=tmpB; } \
|
||
} \
|
||
for (; i<16; i++) { \
|
||
Luma = (int) ((((int)(*Y3++)<<1) - 16) * 1.164); \
|
||
tmpR=cR + Luma; tmpG=cG + Luma; tmpB=cB + Luma; \
|
||
if ((tmpR | tmpG | tmpB) & 0xffffff00) { \
|
||
if (tmpR<0) R[i]=0; else if (tmpR>255) R[i]=255; else R[i]=tmpR; \
|
||
if (tmpG<0) G[i]=0; else if (tmpG>255) G[i]=255; else G[i]=tmpG; \
|
||
if (tmpB<0) B[i]=0; else if (tmpB>255) B[i]=255; else B[i]=tmpB; \
|
||
} else { R[i]=tmpR; G[i]=tmpG; B[i]=tmpB; } \
|
||
}
|
||
|
||
/*
|
||
* Normally, images are stored right side up, that is with the
|
||
* first pixel in the buffer corresponding to the top left pixel
|
||
* in the image.
|
||
*
|
||
* The Microsoft standard Device Independent bitmap formats BI_RGB and
|
||
* BI_BITFIELD are stored with the lower left pixel first. We view that
|
||
* as upside down.
|
||
*
|
||
* Each format can also have a negative height, which also signifes
|
||
* upside down.
|
||
*
|
||
* Since two negatives makes a positive, that means that BI_ formats with
|
||
* negative height are right side up.
|
||
*/
|
||
if( Bmh->biCompression == BI_RGB ||
|
||
Bmh->biCompression == BI_BITFIELDS )
|
||
Ups = 1 ;
|
||
|
||
if( lines < 0 ) {
|
||
Ups = 1-Ups ;
|
||
lines = -lines ;
|
||
}
|
||
|
||
/*
|
||
** The assumption is that YCrCb are subsampled 4:1:1
|
||
** YSize = lines * pixels
|
||
** CbSize = CrSize = (lines*pixels)/4
|
||
*/
|
||
switch (Bmh->biCompression)
|
||
{
|
||
case BI_DECXIMAGEDIB: /* XIMAGE 24 == pBGR */
|
||
case BI_BITFIELDS: /* 32-bit RGB */
|
||
{
|
||
unsigned dword *Iout0 = (unsigned dword *)ImageOut,
|
||
*Iout1, *Iout2, *Iout3;
|
||
if (ValidateBI_BITFIELDS(Bmh) == pRGB)
|
||
for (row = 0; row < lines; row+=4)
|
||
{
|
||
if (Ups) {
|
||
tmp = pixels * (lines-row-1) ;
|
||
Iout0 = (unsigned dword *)ImageOut+tmp;
|
||
Iout1=Iout0-pixels; Iout2=Iout1-pixels; Iout3=Iout2-pixels;
|
||
}
|
||
else {
|
||
Iout1=Iout0+pixels; Iout2=Iout1+pixels; Iout3=Iout2+pixels;
|
||
}
|
||
Y1=Y0+pixels; Y2=Y1+pixels; Y3=Y2+pixels;
|
||
for (col = 0; col < pixels; col += 4)
|
||
{
|
||
if (*Cb & 0x80) /* if 8th bit is set, ignore */
|
||
{
|
||
for (i=0; i<4; i++) {
|
||
*(Iout0++) = 0;
|
||
*(Iout1++) = 0;
|
||
*(Iout2++) = 0;
|
||
*(Iout3++) = 0;
|
||
}
|
||
Cb++; Cr++;
|
||
}
|
||
else
|
||
{
|
||
U = ((*Cb++)<<1) - 128;
|
||
V = ((*Cr++)<<1) - 128;
|
||
_LoadRGBfrom1611();
|
||
for (i=0; i<4; i++)
|
||
*(Iout0++) = (R[i]<<16) | (G[i]<<8) | B[i];
|
||
for (; i<8; i++)
|
||
*(Iout1++) = (R[i]<<16) | (G[i]<<8) | B[i];
|
||
for (; i<12; i++)
|
||
*(Iout2++) = (R[i]<<16) | (G[i]<<8) | B[i];
|
||
for (; i<16; i++)
|
||
*(Iout3++) = (R[i]<<16) | (G[i]<<8) | B[i];
|
||
}
|
||
}
|
||
Iout0=Iout3;
|
||
Y0=Y3;
|
||
}
|
||
else /* pBGR and XIMAGE 24-bit */
|
||
for (row = 0; row < lines; row+=4)
|
||
{
|
||
if (Ups) {
|
||
tmp = pixels * (lines-row-1) ;
|
||
Iout0 = (unsigned dword *)ImageOut+tmp;
|
||
Iout1=Iout0-pixels; Iout2=Iout1-pixels; Iout3=Iout2-pixels;
|
||
}
|
||
else {
|
||
Iout1=Iout0+pixels; Iout2=Iout1+pixels; Iout3=Iout2+pixels;
|
||
}
|
||
Y1=Y0+pixels; Y2=Y1+pixels; Y3=Y2+pixels;
|
||
for (col = 0; col < pixels; col += 4)
|
||
{
|
||
if (*Cb & 0x80) /* if 8th bit is set, ignore */
|
||
{
|
||
for (i=0; i<4; i++) {
|
||
*(Iout0++) = 0;
|
||
*(Iout1++) = 0;
|
||
*(Iout2++) = 0;
|
||
*(Iout3++) = 0;
|
||
}
|
||
Cb++; Cr++;
|
||
}
|
||
else
|
||
{
|
||
U = ((*Cb++)<<1) - 128;
|
||
V = ((*Cr++)<<1) - 128;
|
||
_LoadRGBfrom1611();
|
||
for (i=0; i<4; i++)
|
||
*(Iout0++) = (B[i]<<16) | (G[i]<<8) | R[i];
|
||
for (; i<8; i++)
|
||
*(Iout1++) = (B[i]<<16) | (G[i]<<8) | R[i];
|
||
for (; i<12; i++)
|
||
*(Iout2++) = (B[i]<<16) | (G[i]<<8) | R[i];
|
||
for (; i<16; i++)
|
||
*(Iout3++) = (B[i]<<16) | (G[i]<<8) | R[i];
|
||
}
|
||
}
|
||
Iout0=Iout3;
|
||
Y0=Y3;
|
||
}
|
||
}
|
||
break;
|
||
case BI_RGB:
|
||
switch (Bmh->biBitCount)
|
||
{
|
||
case 15:
|
||
case 16:
|
||
{
|
||
u_short *Sout0 = (u_short *)ImageOut, *Sout1, *Sout2, *Sout3;
|
||
for (row = 0; row < lines; row+=4)
|
||
{
|
||
if (Ups) {
|
||
tmp = pixels * (lines-row-1) ;
|
||
Sout0 = &((u_short *)ImageOut)[tmp]; /* For 32-bit */
|
||
Sout1=Sout0-pixels; Sout2=Sout1-pixels; Sout3=Sout2-pixels;
|
||
}
|
||
else {
|
||
Sout1=Sout0+pixels; Sout2=Sout1+pixels; Sout3=Sout2+pixels;
|
||
}
|
||
Y1=Y0+pixels; Y2=Y1+pixels; Y3=Y2+pixels;
|
||
for (col = 0; col < pixels; col += 4)
|
||
{
|
||
if (*Cb & 0x80) /* if 8th bit is set, ignore */
|
||
{
|
||
for (i=0; i<4; i++) {
|
||
*(Sout0++) = 0;
|
||
*(Sout1++) = 0;
|
||
*(Sout2++) = 0;
|
||
*(Sout3++) = 0;
|
||
}
|
||
Cb++; Cr++;
|
||
}
|
||
else
|
||
{
|
||
U = ((*Cb++)<<1) - 128;
|
||
V = ((*Cr++)<<1) - 128;
|
||
_LoadRGBfrom1611();
|
||
for (i=0; i<4; i++)
|
||
*(Sout0++)=
|
||
((R[i]&0xf8)<<7)|((G[i]&0xf8)<<2)|((B[i]&0xf8)>>3);
|
||
for (; i<8; i++)
|
||
*(Sout1++)=
|
||
((R[i]&0xf8)<<7)|((G[i]&0xf8)<<2)|((B[i]&0xf8)>>3);
|
||
for (; i<12; i++)
|
||
*(Sout2++)=
|
||
((R[i]&0xf8)<<7)|((G[i]&0xf8)<<2)|((B[i]&0xf8)>>3);
|
||
for (; i<16; i++)
|
||
*(Sout3++)=
|
||
((R[i]&0xf8)<<7)|((G[i]&0xf8)<<2)|((B[i]&0xf8)>>3);
|
||
}
|
||
}
|
||
Sout0=Sout3;
|
||
Y0=Y3;
|
||
}
|
||
}
|
||
break;
|
||
case 24:
|
||
{
|
||
u_char *Cout0 = (u_char *)ImageOut, *Cout1, *Cout2, *Cout3;
|
||
for (row = 0; row < lines; row+=4)
|
||
{
|
||
if (Ups) {
|
||
tmp = pixels * (lines-row-1) ;
|
||
Cout0 = &((u_char *)ImageOut)[tmp*3]; /* For 32-bit */
|
||
Cout1=Cout0-pixels; Cout2=Cout1-pixels; Cout3=Cout2-pixels;
|
||
}
|
||
else {
|
||
Cout1=Cout0+pixels; Cout2=Cout1+pixels; Cout3=Cout2+pixels;
|
||
}
|
||
Y1=Y0+pixels; Y2=Y1+pixels; Y3=Y2+pixels;
|
||
for (col = 0; col < pixels; col += 4)
|
||
{
|
||
if (*Cb & 0x80) /* if 8th bit is set, ignore */
|
||
{
|
||
for (i=0; i<4*3; i++) {
|
||
*(Cout0++) = 0;
|
||
*(Cout1++) = 0;
|
||
*(Cout2++) = 0;
|
||
*(Cout3++) = 0;
|
||
}
|
||
Cb++; Cr++;
|
||
}
|
||
else
|
||
{
|
||
U = ((*Cb++)<<1) - 128;
|
||
V = ((*Cr++)<<1) - 128;
|
||
_LoadRGBfrom1611();
|
||
for (i=0; i<4; i++)
|
||
{ *(Cout0++)=(u_char)B[i]; *(Cout0++)=(u_char)G[i]; *(Cout0++)=(u_char)R[i]; }
|
||
for (; i<8; i++)
|
||
{ *(Cout1++)=(u_char)B[i]; *(Cout1++)=(u_char)G[i]; *(Cout1++)=(u_char)R[i]; }
|
||
for (; i<12; i++)
|
||
{ *(Cout2++)=(u_char)B[i]; *(Cout2++)=(u_char)G[i]; *(Cout2++)=(u_char)R[i]; }
|
||
for (; i<16; i++)
|
||
{ *(Cout3++)=(u_char)B[i]; *(Cout3++)=(u_char)G[i]; *(Cout3++)=(u_char)R[i]; }
|
||
}
|
||
}
|
||
Cout0=Cout3;
|
||
Y0=Y3;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
break;
|
||
default:
|
||
return(ScErrorUnrecognizedFormat);
|
||
}
|
||
return (NoErrors);
|
||
}
|
||
|
||
|
||
/*
|
||
** Name: ScYuv422ToRgb
|
||
** Purpose: convert 16-bit YCrCb 4:2:2 to an 24-bit/16-bit/32-bit RGB
|
||
**
|
||
** Note: The code below is pixel based and is *extremely* inefficient, we
|
||
** plan to replace the dumb code below with some fast code
|
||
** If Cb==NULL and Cr==NULL then assume BI_DECGRAYDIB (use only Y component).
|
||
*/
|
||
ScStatus_t ScYuv422ToRgb (BITMAPINFOHEADER *Bmh, u_char *Y, u_char *Cb,
|
||
u_char *Cr, u_char *ImageOut)
|
||
{
|
||
register int row, col;
|
||
register int Luma,U=0,V=0;
|
||
int R1,R2, G1,G2, B1,B2;
|
||
int Ups = 0, tmp; /* Flip image upside down */
|
||
u_char *RData, *GData, *BData; /* pointers for non-interlaced mode */
|
||
u_char *Cout = (u_char *)ImageOut;
|
||
u_short *Sout = (u_short *)ImageOut;
|
||
u_int *Iout = (u_int *)ImageOut;
|
||
int pixels = Bmh->biWidth;
|
||
int lines = Bmh->biHeight;
|
||
#ifdef NEW_YCBCR
|
||
#define _LoadRGBfrom422() \
|
||
if (U || V) { \
|
||
R1 = R2 = (int) ( + (1.596 * V)); \
|
||
G1 = G2 = (int) (- (0.391 * U) - (0.813 * V)); \
|
||
B1 = B2 = (int) (+ (2.018 * U) ); \
|
||
} else { R1=R2=G1=G2=B1=B2=0; } \
|
||
Luma = (int) (((int) *(Y++) - 16) * 1.164); \
|
||
R1 += Luma; G1 += Luma; B1 += Luma; \
|
||
Luma = (int) (((int) *(Y++) - 16) * 1.164); \
|
||
R2 += Luma; G2 += Luma; B2 += Luma; \
|
||
if ((R1 | G1 | B1 | R2 | G2 | B2) & 0xffffff00) { \
|
||
if (R1<0) R1=0; else if (R1>255) R1=255; \
|
||
if (G1<0) G1=0; else if (G1>255) G1=255; \
|
||
if (B1<0) B1=0; else if (B1>255) B1=255; \
|
||
if (R2<0) R2=0; else if (R2>255) R2=255; \
|
||
if (G2<0) G2=0; else if (G2>255) G2=255; \
|
||
if (B2<0) B2=0; else if (B2>255) B2=255; \
|
||
}
|
||
#else
|
||
#define _LoadRGBfrom422() \
|
||
Luma = *(Y++); \
|
||
R1 = Luma + (1.4075 * V); \
|
||
G1 = Luma - (0.3455 * U) - (0.7169 * V); \
|
||
B1 = Luma + (1.7790 * U); \
|
||
Luma = *(Y++); \
|
||
R2 = Luma + (1.4075 * V); \
|
||
G2 = Luma - (0.3455 * U) - (0.7169 * V); \
|
||
B2 = Luma + (1.7790 * U); \
|
||
if ((R1 | G1 | B1 | R2 | G2 | B2) & 0xffffff00) { \
|
||
if (R1<0) R1=0; else if (R1>255) R1=255; \
|
||
if (G1<0) G1=0; else if (G1>255) G1=255; \
|
||
if (B1<0) B1=0; else if (B1>255) B1=255; \
|
||
if (R2<0) R2=0; else if (R2>255) R2=255; \
|
||
if (G2<0) G2=0; else if (G2>255) G2=255; \
|
||
if (B2<0) B2=0; else if (B2>255) B2=255; \
|
||
}
|
||
#endif /* NEW_YCBCR */
|
||
|
||
/*
|
||
* Normally, images are stored right side up,
|
||
* that is with the first pixel in the buffer
|
||
* corresponding to the top left pixel in the image.
|
||
*
|
||
* The Microsoft standard Device Independent bitmap
|
||
* formats BI_RGB and BI_BITFIELD are stored with
|
||
* the lower left pixel first.
|
||
* We view that as upside down.
|
||
*
|
||
* Each format can also have a negative height,
|
||
* which also signifes upside down.
|
||
*
|
||
* Since two negatives makes a positive, that means
|
||
* that BI_ formats with a negative height are right side up.
|
||
*/
|
||
|
||
if( Bmh->biCompression == BI_RGB ||
|
||
Bmh->biCompression == BI_BITFIELDS)
|
||
Ups = 1 ;
|
||
|
||
if( lines < 0 ) {
|
||
Ups = 1-Ups ;
|
||
lines = -lines ;
|
||
}
|
||
|
||
/*
|
||
** needed if the three components are to be provided in a
|
||
** non-interlaced mode:
|
||
*/
|
||
if (Bmh->biCompression == BI_DECSEPRGBDIB) {
|
||
RData = ImageOut;
|
||
GData = RData + (pixels * lines);
|
||
BData = GData + (pixels * lines);
|
||
}
|
||
|
||
|
||
/*
|
||
** The assumption is that YCrCb are subsampled 4:2:2
|
||
** YSize = lines * pixels
|
||
** CbSize = CrSize = (lines*pixels)/2
|
||
*/
|
||
switch (Bmh->biCompression)
|
||
{
|
||
case BI_RGB:
|
||
switch (Bmh->biBitCount)
|
||
{
|
||
case 15:
|
||
case 16:
|
||
{
|
||
u_short *Sout = (u_short *)ImageOut;
|
||
for (row = 0; row < lines; row++)
|
||
{
|
||
if (Ups)
|
||
{
|
||
tmp = pixels * (lines-row-1) ;
|
||
Sout = &((u_short *)ImageOut)[tmp]; /* For 16-bit */
|
||
}
|
||
for (col = 0; col < pixels; col += 2)
|
||
{
|
||
if (Cb) {
|
||
U = *Cb++ - 128;
|
||
V = *Cr++ - 128;
|
||
}
|
||
_LoadRGBfrom422();
|
||
*(Sout++) = ((R1&0xf8)<<7)|((G1&0xf8)<<2)|((B1&0xf8)>>3);
|
||
*(Sout++) = ((R2&0xf8)<<7)|((G2&0xf8)<<2)|((B2&0xf8)>>3);
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case 24:
|
||
{
|
||
u_char *Cout = (u_char *)ImageOut;
|
||
for (row = 0; row < lines; row++)
|
||
{
|
||
if (Ups)
|
||
{
|
||
tmp = pixels * (lines-row-1) ;
|
||
Cout = &((u_char *)ImageOut)[3*tmp]; /* For 24-bit */
|
||
}
|
||
for (col = 0; col < pixels; col += 2)
|
||
{
|
||
if (Cb) {
|
||
U = *Cb++ - 128;
|
||
V = *Cr++ - 128;
|
||
}
|
||
_LoadRGBfrom422();
|
||
*(Cout++) = (u_char)B1; *(Cout++) = (u_char)G1; *(Cout++) = (u_char)R1;
|
||
*(Cout++) = (u_char)B2; *(Cout++) = (u_char)G2; *(Cout++) = (u_char)R2;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case 32:
|
||
{
|
||
u_int *Iout = (u_int *)ImageOut;
|
||
for (row = 0; row < lines; row++)
|
||
{
|
||
if (Ups)
|
||
{
|
||
tmp = pixels * (lines-row-1) ;
|
||
Iout = &((u_int *)ImageOut)[tmp]; /* For 32-bit */
|
||
}
|
||
for (col = 0; col < pixels; col += 2)
|
||
{
|
||
if (Cb) {
|
||
U = *Cb++ - 128;
|
||
V = *Cr++ - 128;
|
||
}
|
||
_LoadRGBfrom422();
|
||
*(Iout++) = (R1<<16) | (G1<<8) | B1 ;
|
||
*(Iout++) = (R2<<16) | (G2<<8) | B2 ;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
break;
|
||
case BI_DECSEPRGBDIB: /* 24-bit separate RGB */
|
||
{
|
||
u_char *RData, *GData, *BData;
|
||
RData = ImageOut;
|
||
GData = RData + (pixels * lines);
|
||
BData = GData + (pixels * lines);
|
||
for (row = 0; row < lines; row++)
|
||
{
|
||
for (col = 0; col < pixels; col += 2)
|
||
{
|
||
if (Cb) {
|
||
U = *Cb++ - 128;
|
||
V = *Cr++ - 128;
|
||
}
|
||
_LoadRGBfrom422();
|
||
*(RData++) = (u_char)R1; *(RData++) = (u_char)R2;
|
||
*(GData++) = (u_char)G1; *(GData++) = (u_char)G2;
|
||
*(BData++) = (u_char)B1; *(BData++) = (u_char)B2;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
case BI_DECXIMAGEDIB: /* XIMAGE 24 == pBGR */
|
||
case BI_BITFIELDS: /* 16 or 32-bit RGB */
|
||
switch (Bmh->biBitCount)
|
||
{
|
||
case 16:
|
||
{ /* 16-bit BI_BITFIELDS, hardcoded to RGB565 */
|
||
u_short *Sout = (u_short *)ImageOut;
|
||
for (row = 0; row < lines; row++)
|
||
{
|
||
if (Ups)
|
||
{
|
||
tmp = pixels * (lines-row-1) ;
|
||
Sout = &((u_short *)ImageOut)[tmp]; /* For 16-bit */
|
||
}
|
||
for (col = 0; col < pixels; col += 2)
|
||
{
|
||
if (Cb) {
|
||
U = *Cb++ - 128;
|
||
V = *Cr++ - 128;
|
||
}
|
||
_LoadRGBfrom422();
|
||
*(Sout++) = ((R1<<8) & 0xf800) | ((G1<<3) & 0x07e0) | ((B1>>3) & 0x01f);
|
||
*(Sout++) = ((R2<<8) & 0xf800) | ((G2<<3) & 0x07e0) | ((B2>>3) & 0x01f);
|
||
}
|
||
}
|
||
}
|
||
break ;
|
||
case 24:
|
||
case 32:
|
||
{ /* 32-bit RGB */
|
||
u_int *Iout = (u_int *)ImageOut;
|
||
if (ValidateBI_BITFIELDS(Bmh) == pRGB)
|
||
{
|
||
for (row = 0; row < lines; row++)
|
||
{
|
||
if (Ups)
|
||
{
|
||
tmp = pixels * (lines-row-1) ;
|
||
Iout = &((u_int *)ImageOut)[tmp]; /* For 32-bit */
|
||
}
|
||
for (col = 0; col < pixels; col += 2)
|
||
{
|
||
if (Cb) {
|
||
U = *Cb++ - 128;
|
||
V = *Cr++ - 128;
|
||
}
|
||
_LoadRGBfrom422();
|
||
*(Iout++) = (R1<<16) | (G1<<8) | B1;
|
||
*(Iout++) = (R2<<16) | (G2<<8) | B2;
|
||
}
|
||
}
|
||
}
|
||
else /* pBGR and XIMAGE 24-bit */
|
||
{
|
||
for (row = 0; row < lines; row++)
|
||
{
|
||
if (Ups)
|
||
{
|
||
tmp = pixels * (lines-row-1) ;
|
||
Iout = &((u_int *)ImageOut)[tmp]; /* For 32-bit */
|
||
}
|
||
for (col = 0; col < pixels; col += 2)
|
||
{
|
||
if (Cb) {
|
||
U = *Cb++ - 128;
|
||
V = *Cr++ - 128;
|
||
}
|
||
_LoadRGBfrom422();
|
||
*(Iout++) = (B1<<16) | (G1<<8) | R1;
|
||
*(Iout++) = (B2<<16) | (G2<<8) | R2;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
break;
|
||
default:
|
||
return(ScErrorUnrecognizedFormat);
|
||
}
|
||
return (NoErrors);
|
||
}
|
||
|
||
/*
|
||
** Name: ScInitRgbToYuv
|
||
** Purpose: Initializes tables for RGB to YUV conversion.
|
||
**
|
||
** Notes:
|
||
**
|
||
** The tables are allocated and filled in once the first
|
||
** time they are needed. They will remin for the lifetime
|
||
** of the server.
|
||
**
|
||
** The following formula is used:
|
||
**
|
||
** y = 0.257 * r + 0.504 * g + 0.098 * b + 16 ; /+ 16 - 235 +/
|
||
** u = -0.148 * r - 0.291 * g + 0.439 * b + 128 ; /+ 16 - 239 +/
|
||
** v = 0.439 * r - 0.368 * g - 0.071 * b + 128 ; /+ 16 - 239 +/
|
||
**
|
||
** But we rewrite it thus:
|
||
**
|
||
** y = 16.000 + 0.257 * r + 0.504 * g + 0.098 * b ;
|
||
** u = 16.055 + 0.148 * (255-r) + 0.291 * (255-g) + 0.439 * b ;
|
||
** v = 16.055 + 0.439 * r + 0.368 * (255-g) + 0.071 * (255-b) ;
|
||
**
|
||
** ( By the way, the old constants are: )
|
||
** ( y = r * 0.299 + g * 0.587 + b * 0.114 ; )
|
||
** ( u = r * -0.169 + g * -0.332 + b * 0.500 + 128 ; )
|
||
** ( v = r * 0.500 + g * -0.419 + b * -0.0813 + 128 ; )
|
||
** ( or )
|
||
** ( y = 0.0 + 0.299 * r + 0.587 * g + 0.1140 * b ; )
|
||
** ( u = 0.245 + 0.169 * (255-r) + 0.332 * (255-g) + 0.5000 * b ; )
|
||
** ( v = 0.4235 + 0.500 * r + 0.419 * (255-g) + 0.0813 * (255-b) ; )
|
||
**
|
||
** This particular arrangement of the formula allows Y, U and V values
|
||
** to be calculated in paralell by simple table lookup.
|
||
** The paralellism comes from the fact that Y,U and V values
|
||
** are stored in the same word, but in different bytes.
|
||
** The tables are such that the contribution from red, green
|
||
** and blue can simply be added together, without any carry
|
||
** between bytes. Since the YUV space is larger than the RGB
|
||
** cube, and the RGB cube fits entirely within YUV space,
|
||
** there is no overflow and no range checking is needed.
|
||
**
|
||
*/
|
||
|
||
#ifdef NEW_YCBCR
|
||
/*
|
||
** y = 16.000 + 0.257 * r + 0.504 * g + 0.098 * b ;
|
||
** u = 16.055 + 0.148 * (255-r) + 0.291 * (255-g) + 0.439 * b ;
|
||
** v = 16.055 + 0.439 * r + 0.368 * (255-g) + 0.071 * (255-b) ;
|
||
*/
|
||
#define YC 16.000
|
||
#define UC 16.055
|
||
#define VC 16.055
|
||
#define YR 0.257
|
||
#define UR 0.148
|
||
#define VR 0.439
|
||
#define YG 0.504
|
||
#define UG 0.291
|
||
#define VG 0.368
|
||
#define YB 0.098
|
||
#define UB 0.439
|
||
#define VB 0.071
|
||
|
||
#else /* !NEW_YCBCR */
|
||
/*
|
||
** ( y = 0.0 0.299 * r + 0.587 * g + 0.1140 * b ; )
|
||
** ( u = 0.245 + 0.169 * (255-r) + 0.332 * (255-g) + 0.5000 * b ; )
|
||
** ( v = 0.4235 + 0.500 * r + 0.419 * (255-g) + 0.0813 * (255-b) ; )
|
||
*/
|
||
#define YC 0.0
|
||
#define UC 0.245
|
||
#define VC 0.4235
|
||
#define YR 0.299
|
||
#define UR 0.169
|
||
#define VR 0.500
|
||
#define YG 0.587
|
||
#define UG 0.332
|
||
#define VG 0.419
|
||
#define YB 0.1140
|
||
#define UB 0.5000
|
||
#define VB 0.0813
|
||
|
||
#endif /* !NEW_YCBCR */
|
||
|
||
/*
|
||
* We only need an int (32 bits) per table entry but
|
||
* 64-bit aligned access is faster on alpha.
|
||
*/
|
||
|
||
#ifdef __alpha
|
||
_int64 *RedToYuyv, *GreenToYuyv, *BlueToYuyv ;
|
||
#else /* !__alpha */
|
||
unsigned int *RedToYuyv, *GreenToYuyv, *BlueToYuyv ;
|
||
#endif /* !__alpha */
|
||
|
||
int ScInitRgbToYuv()
|
||
{
|
||
int i, y, u, v ;
|
||
|
||
if( RedToYuyv == NULL ) {
|
||
#ifdef __alpha
|
||
RedToYuyv = (_int64 *) ScAlloc( 256 * sizeof( _int64 ) ) ;
|
||
GreenToYuyv = (_int64 *) ScAlloc( 256 * sizeof( _int64 ) ) ;
|
||
BlueToYuyv = (_int64 *) ScAlloc( 256 * sizeof( _int64 ) ) ;
|
||
#else /* !__alpha */
|
||
RedToYuyv = (unsigned int *) ScAlloc( 256 * sizeof( unsigned int ) ) ;
|
||
GreenToYuyv = (unsigned int *) ScAlloc( 256 * sizeof( unsigned int ) ) ;
|
||
BlueToYuyv = (unsigned int *) ScAlloc( 256 * sizeof( unsigned int ) ) ;
|
||
#endif /* !__alpha */
|
||
|
||
if( !RedToYuyv || !GreenToYuyv || !BlueToYuyv )
|
||
return 0 ;
|
||
|
||
for( i=0 ; i<256 ; i++ ) {
|
||
|
||
/*
|
||
* Calculate contribution from red.
|
||
* We will also add in the constant here.
|
||
* Pack it into the tables thus: lsb->YUYV<-msb
|
||
*/
|
||
|
||
y = (int) (YC + YR * i) ;
|
||
u = (int) (UC + UR * (255-i)) ;
|
||
v = (int) (VC + VR * i) ;
|
||
RedToYuyv[i] = (y | (u<<8) | (y<<16) | (v<<24)) ;
|
||
|
||
/*
|
||
* Calculate contribution from green.
|
||
*/
|
||
|
||
y = (int) (YG * i) ;
|
||
u = (int) (UG * (255-i)) ;
|
||
v = (int) (VG * (255-i)) ;
|
||
GreenToYuyv[i] = (y | (u<<8) | (y<<16) | (v<<24)) ;
|
||
|
||
/*
|
||
* Calculate contribution from blue.
|
||
*/
|
||
|
||
y = (int) (YB * i) ;
|
||
u = (int) (UB * i) ;
|
||
v = (int) (VB * (255-i)) ;
|
||
BlueToYuyv[i] = (y | (u<<8) | (y<<16) | (v<<24)) ;
|
||
|
||
}
|
||
}
|
||
return 1 ;
|
||
}
|
||
|
||
/*
|
||
** Name: ScConvertRGB24sTo422i_C
|
||
** Purpose: convert 24-bit RGB (8:8:8 format) to 16-bit YCrCb (4:2:2 format)
|
||
*/
|
||
ScStatus_t ScConvertRGB24sTo422i_C(BITMAPINFOHEADER *Bmh, u_char *R, u_char *G,
|
||
u_char *B, u_short *ImageOut)
|
||
{
|
||
register int row, col;
|
||
int yuyv,r,g,b;
|
||
int pixels = Bmh->biWidth;
|
||
int lines = abs(Bmh->biHeight);
|
||
|
||
if( !RedToYuyv && !ScInitRgbToYuv() )
|
||
return ScErrorMemory ;
|
||
|
||
for (row = 0; row < lines; row++) {
|
||
for (col = 0; col < pixels; col++) {
|
||
r = *(R++); g = *(G++); b = *(B++);
|
||
|
||
/*
|
||
* Quick convert to YUV.
|
||
*/
|
||
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]) ;
|
||
|
||
/*
|
||
* Pack 4:2:2 = YUYV YUYV ...
|
||
* We'll pack YU or YV depending on whether col is odd or not.
|
||
* Shift yuyv 0 for even, 16 for odd columns.
|
||
*/
|
||
|
||
*(ImageOut++) = yuyv >> ((col & 1) << 4) ;
|
||
|
||
}
|
||
}
|
||
return (NoErrors);
|
||
}
|
||
|
||
#define M_RND(f) ((int) ((f) + .5))
|
||
|
||
/*
|
||
** Name: ScConvertRGB24To411s_C
|
||
** Purpose: convert 24-bit RGB (8:8:8 format) to 16-bit YCrCb (4:1:1 format)
|
||
*/
|
||
ScStatus_t ScConvertRGB24To411s_C(u_char *inimage,
|
||
u_char *Y, u_char *U, u_char *V,
|
||
int width, int height)
|
||
{
|
||
register int row, col;
|
||
int yuyv, r, g, b;
|
||
u_char *tmp, *evl, *odl;
|
||
|
||
if( !RedToYuyv && !ScInitRgbToYuv() )
|
||
return(ScErrorMemory);
|
||
if (height<0) /* flip image */
|
||
{
|
||
height = -height;
|
||
for (row = height-1; row; row--)
|
||
{
|
||
tmp = inimage+(width*row*3);
|
||
if (row & 1)
|
||
{
|
||
odl = tmp;
|
||
evl = tmp-(width*3);
|
||
}
|
||
else
|
||
{
|
||
evl = tmp;
|
||
odl = tmp-(width*3);
|
||
}
|
||
for (col = 0; col < width; col++)
|
||
{
|
||
r = *tmp++;
|
||
g = *tmp++;
|
||
b = *tmp++;
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]);
|
||
*Y++ = (yuyv&0xff);
|
||
|
||
/* We only store every fourth value of u and v components */
|
||
if ((col & 1) && (row & 1))
|
||
{
|
||
/* Compute average r, g and b values */
|
||
r = *evl++ + *odl++;
|
||
g = *evl++ + *odl++;
|
||
b = *evl++ + *odl++;
|
||
r += (*evl++ + *odl++);
|
||
g += (*evl++ + *odl++);
|
||
b += (*evl++ + *odl++);
|
||
r = r >> 2;
|
||
g = g >> 2;
|
||
b = b >> 2;
|
||
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]);
|
||
*U++ = ((yuyv&0xff000000) >> 24); // V
|
||
*V++ = ((yuyv&0xff00) >> 8); // U
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
tmp = inimage;
|
||
for (row = 0; row < height; row++)
|
||
{
|
||
if (row & 1)
|
||
odl = tmp;
|
||
else
|
||
evl = tmp;
|
||
for (col = 0; col < width; col++)
|
||
{
|
||
r = *tmp++;
|
||
g = *tmp++;
|
||
b = *tmp++;
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]);
|
||
*Y++ = (yuyv&0xff);
|
||
|
||
/* We only store every fourth value of u and v components */
|
||
if ((col & 1) && (row & 1))
|
||
{
|
||
/* Compute average r, g and b values */
|
||
r = *evl++ + *odl++;
|
||
g = *evl++ + *odl++;
|
||
b = *evl++ + *odl++;
|
||
r += (*evl++ + *odl++);
|
||
g += (*evl++ + *odl++);
|
||
b += (*evl++ + *odl++);
|
||
r = r >> 2;
|
||
g = g >> 2;
|
||
b = b >> 2;
|
||
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]);
|
||
*U++ = ((yuyv&0xff000000) >> 24); // V
|
||
*V++ = ((yuyv&0xff00) >> 8); // U
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return (NoErrors);
|
||
}
|
||
|
||
/*
|
||
** Name: ScConvertRGB555To411s_C
|
||
** Purpose: convert 16-bit RGB (5:5:5 format) to 16-bit YCrCb (4:1:1 format)
|
||
*/
|
||
ScStatus_t ScConvertRGB555To411s_C(u_char *inimage, u_char *outimage,
|
||
int width, int height)
|
||
{
|
||
u_char *Y=outimage, *U, *V;
|
||
register int row, col, inpixel;
|
||
int yuyv, r, g, b;
|
||
unsigned word *tmp, *evl, *odl;
|
||
|
||
#define GetRGB555(in16, r, g, b) b = (inpixel>>7)&0xF8; \
|
||
g = (inpixel>>2)&0xF8; \
|
||
r = (inpixel<<3)&0xF8
|
||
|
||
#define AddRGB555(in16, r, g, b) b += (inpixel>>7)&0xF8; \
|
||
g += (inpixel>>2)&0xF8; \
|
||
r += (inpixel<<3)&0xF8
|
||
|
||
if( !RedToYuyv && !ScInitRgbToYuv() )
|
||
return(ScErrorMemory);
|
||
if (height<0) /* flip image */
|
||
{
|
||
height = -height;
|
||
U=Y+(width*height);
|
||
V=U+(width*height*1)/4;
|
||
for (row = height-1; row; row--)
|
||
{
|
||
tmp = ((unsigned word *)inimage)+(width*row);
|
||
if (row & 1)
|
||
{
|
||
odl = tmp;
|
||
evl = tmp-width;
|
||
}
|
||
else
|
||
{
|
||
evl = tmp;
|
||
odl = tmp-width;
|
||
}
|
||
for (col = 0; col < width; col++)
|
||
{
|
||
inpixel=*tmp++;
|
||
GetRGB555(inpixel, r, g, b);
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]);
|
||
*Y++ = (yuyv&0xff);
|
||
|
||
/* We only store every fourth value of u and v components */
|
||
if ((col & 1) && (row & 1))
|
||
{
|
||
/* Compute average r, g and b values */
|
||
inpixel=*evl++;
|
||
GetRGB555(inpixel, r, g, b);
|
||
inpixel=*evl++;
|
||
AddRGB555(inpixel, r, g, b);
|
||
inpixel=*odl++;
|
||
AddRGB555(inpixel, r, g, b);
|
||
inpixel=*odl++;
|
||
AddRGB555(inpixel, r, g, b);
|
||
r = r >> 2;
|
||
g = g >> 2;
|
||
b = b >> 2;
|
||
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]);
|
||
*U++ = ((yuyv&0xff000000) >> 24); // V
|
||
*V++ = ((yuyv&0xff00) >> 8); // U
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
U=Y+(width*height);
|
||
V=U+(width*height*1)/4;
|
||
tmp = (unsigned word *)inimage;
|
||
for (row = 0; row < height; row++)
|
||
{
|
||
if (row & 1)
|
||
odl = tmp;
|
||
else
|
||
evl = tmp;
|
||
for (col = 0; col < width; col++)
|
||
{
|
||
inpixel=*tmp++;
|
||
GetRGB555(inpixel, r, g, b);
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]);
|
||
*Y++ = (yuyv&0xff);
|
||
|
||
/* We only store every fourth value of u and v components */
|
||
if ((col & 1) && (row & 1))
|
||
{
|
||
/* Compute average r, g and b values */
|
||
inpixel=*evl++;
|
||
GetRGB555(inpixel, r, g, b);
|
||
inpixel=*evl++;
|
||
AddRGB555(inpixel, r, g, b);
|
||
inpixel=*odl++;
|
||
AddRGB555(inpixel, r, g, b);
|
||
inpixel=*odl++;
|
||
AddRGB555(inpixel, r, g, b);
|
||
r = r >> 2;
|
||
g = g >> 2;
|
||
b = b >> 2;
|
||
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]);
|
||
*U++ = ((yuyv&0xff000000) >> 24); // V
|
||
*V++ = ((yuyv&0xff00) >> 8); // U
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return (NoErrors);
|
||
}
|
||
|
||
/*
|
||
** Name: ScConvertRGB565To411s_C
|
||
** Purpose: convert 16-bit RGB (5:6:5 format) to 16-bit YCrCb (4:1:1 format)
|
||
*/
|
||
ScStatus_t ScConvertRGB565To411s_C(u_char *inimage, u_char *outimage,
|
||
int width, int height)
|
||
{
|
||
u_char *Y=outimage, *U, *V;
|
||
register int row, col, inpixel;
|
||
int yuyv, r, g, b;
|
||
unsigned word *tmp, *evl, *odl;
|
||
|
||
#define GetRGB565(in16, r, g, b) b = (inpixel>>8)&0xF8; \
|
||
g = (inpixel>>3)&0xFC; \
|
||
r = (inpixel<<3)&0xF8
|
||
|
||
#define AddRGB565(in16, r, g, b) b += (inpixel>>8)&0xF8; \
|
||
g += (inpixel>>3)&0xFC; \
|
||
r += (inpixel<<3)&0xF8
|
||
|
||
if( !RedToYuyv && !ScInitRgbToYuv() )
|
||
return(ScErrorMemory);
|
||
if (height<0) /* flip image */
|
||
{
|
||
height = -height;
|
||
U=Y+(width*height);
|
||
V=U+(width*height*1)/4;
|
||
for (row = height-1; row; row--)
|
||
{
|
||
tmp = ((unsigned word *)inimage)+(width*row);
|
||
if (row & 1)
|
||
{
|
||
odl = tmp;
|
||
evl = tmp-width;
|
||
}
|
||
else
|
||
{
|
||
evl = tmp;
|
||
odl = tmp-width;
|
||
}
|
||
for (col = 0; col < width; col++)
|
||
{
|
||
inpixel=*tmp++;
|
||
GetRGB565(inpixel, r, g, b);
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]);
|
||
*Y++ = (yuyv&0xff);
|
||
|
||
/* We only store every fourth value of u and v components */
|
||
if ((col & 1) && (row & 1))
|
||
{
|
||
/* Compute average r, g and b values */
|
||
inpixel=*evl++;
|
||
GetRGB565(inpixel, r, g, b);
|
||
inpixel=*evl++;
|
||
AddRGB565(inpixel, r, g, b);
|
||
inpixel=*odl++;
|
||
AddRGB565(inpixel, r, g, b);
|
||
inpixel=*odl++;
|
||
AddRGB565(inpixel, r, g, b);
|
||
r = r >> 2;
|
||
g = g >> 2;
|
||
b = b >> 2;
|
||
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]);
|
||
*U++ = ((yuyv&0xff000000) >> 24); // V
|
||
*V++ = ((yuyv&0xff00) >> 8); // U
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
U=Y+(width*height);
|
||
V=U+(width*height*1)/4;
|
||
tmp = (unsigned word *)inimage;
|
||
for (row = 0; row < height; row++)
|
||
{
|
||
if (row & 1)
|
||
odl = tmp;
|
||
else
|
||
evl = tmp;
|
||
for (col = 0; col < width; col++)
|
||
{
|
||
inpixel=*tmp++;
|
||
GetRGB565(inpixel, r, g, b);
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]);
|
||
*Y++ = (yuyv&0xff);
|
||
|
||
/* We only store every fourth value of u and v components */
|
||
if ((col & 1) && (row & 1))
|
||
{
|
||
/* Compute average r, g and b values */
|
||
inpixel=*evl++;
|
||
GetRGB565(inpixel, r, g, b);
|
||
inpixel=*evl++;
|
||
AddRGB565(inpixel, r, g, b);
|
||
inpixel=*odl++;
|
||
AddRGB565(inpixel, r, g, b);
|
||
inpixel=*odl++;
|
||
AddRGB565(inpixel, r, g, b);
|
||
r = r >> 2;
|
||
g = g >> 2;
|
||
b = b >> 2;
|
||
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]);
|
||
*U++ = ((yuyv&0xff000000) >> 24); // V
|
||
*V++ = ((yuyv&0xff00) >> 8); // U
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return (NoErrors);
|
||
}
|
||
|
||
/*
|
||
** Name: ScRgbInterlToYuvInterl
|
||
** Purpose: convert many RGB formats to 16-bit YCrCb (4:2:2 format)
|
||
*/
|
||
ScStatus_t ScRgbInterlToYuvInterl (
|
||
LPBITMAPINFOHEADER Bmh,
|
||
int Width,
|
||
int Height,
|
||
u_char *ImageIn,
|
||
u_short *ImageOut)
|
||
{
|
||
register int row, col;
|
||
int yuyv,r,g,b,mask=0x00ff;
|
||
int pixels = Width;
|
||
int lines = abs(Height);
|
||
int IspBGR = (ValidateBI_BITFIELDS(Bmh) == pBGR) ||
|
||
(Bmh->biCompression==BI_DECXIMAGEDIB && Bmh->biBitCount==24);
|
||
int IspRGB_BI_RGB_24 = (Bmh->biCompression==BI_RGB && Bmh->biBitCount==24);
|
||
int linestep = 0 ;
|
||
|
||
if( !RedToYuyv && !ScInitRgbToYuv() )
|
||
return ScErrorMemory ;
|
||
|
||
/*
|
||
* Check the input format and decide
|
||
* whether the image is to be turned
|
||
* upside down or not.
|
||
*/
|
||
|
||
if( (Bmh->biCompression == BI_RGB ||
|
||
Bmh->biCompression == BI_BITFIELDS) ^
|
||
((int) Bmh->biHeight < 0) ) {
|
||
ImageOut = &ImageOut[ pixels * (lines - 1) ] ;
|
||
linestep = -(pixels << 1) ;
|
||
}
|
||
|
||
/*
|
||
* To avoid if-then-else statements inside
|
||
* the inner loop, we have 3 loops.
|
||
*/
|
||
|
||
/*
|
||
* 24 bits per pixel RGB.
|
||
*/
|
||
|
||
if (IspRGB_BI_RGB_24) {
|
||
|
||
for (row = 0; row < lines; row++) {
|
||
for (col = 0; col < pixels; col++) {
|
||
b = *(ImageIn++);
|
||
g = *(ImageIn++);
|
||
r = *(ImageIn++);
|
||
|
||
/*
|
||
* Quick convert from RGB to YUV. Just add together
|
||
* the contributions from each of Red, Green and Blue.
|
||
*/
|
||
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]) ;
|
||
|
||
/*
|
||
* Pack 4:2:2 = YUYV YUYV ...
|
||
* We'll pack YU or YV depending on whether col is odd or not.
|
||
* Shift yuyv 0 for even, 16 for odd columns.
|
||
*/
|
||
|
||
*(ImageOut++) = yuyv >> ((col & 1) << 4) ;
|
||
|
||
}
|
||
/*
|
||
* In case we're turning the image upside down.
|
||
* This will do nothing if it's right side up.
|
||
*/
|
||
ImageOut = &ImageOut[linestep] ;
|
||
}
|
||
}
|
||
/*
|
||
* 32 bits per pixels 0BGR.
|
||
*/
|
||
else if (IspBGR) {
|
||
for (row = 0; row < lines; row++) {
|
||
for (col = 0; col < pixels; col++) {
|
||
r = *((int *) ImageIn)++ ;
|
||
b = (r>>16) & mask ;
|
||
g = (r>> 8) & mask ;
|
||
r &= mask ;
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]) ;
|
||
*(ImageOut++) = yuyv >> ((col & 1) << 4) ;
|
||
}
|
||
ImageOut = &ImageOut[linestep] ;
|
||
}
|
||
}
|
||
/*
|
||
* 32 bits per pixels 0RGB.
|
||
*/
|
||
else {
|
||
for (row = 0; row < lines; row++) {
|
||
for (col = 0; col < pixels; col++) {
|
||
b = *((int *) ImageIn)++ ;
|
||
r = (b>>16) & mask ;
|
||
g = (b>> 8) & mask ;
|
||
b &= mask ;
|
||
yuyv = (int) (RedToYuyv[r] + GreenToYuyv[g] + BlueToYuyv[b]) ;
|
||
*(ImageOut++) = yuyv >> ((col & 1) << 4) ;
|
||
}
|
||
ImageOut = &ImageOut[linestep] ;
|
||
}
|
||
}
|
||
|
||
return (NoErrors);
|
||
}
|
||
|
||
|
||
/*
|
||
** Function: ScConvert422ToYUV_char_C
|
||
** Purpose: Extract the Y, U and V components into separate planes.
|
||
** The interleaved format is YUYV, 4:2:2, we want 4:1:1 so,
|
||
** only copy every other line of the chrominance
|
||
*/
|
||
ScStatus_t ScConvert422ToYUV_char_C (u_char *RawImage,
|
||
u_char *Y, u_char *U, u_char *V,
|
||
int Width, int Height)
|
||
{
|
||
register int x, y;
|
||
|
||
Width/=2;
|
||
Height=abs(Height)/2;
|
||
for (y = 0; y < Height; y++)
|
||
{
|
||
for (x = 0 ; x < Width; x++)
|
||
{
|
||
*Y++ = *RawImage++;
|
||
*U++ = *RawImage++;
|
||
*Y++ = *RawImage++;
|
||
*V++ = *RawImage++;
|
||
}
|
||
for (x = 0; x < Width; x++)
|
||
{
|
||
*Y++ = *RawImage;
|
||
RawImage+=2;
|
||
*Y++ = *RawImage;
|
||
RawImage+=2;
|
||
}
|
||
}
|
||
return (NoErrors);
|
||
}
|
||
|
||
/*
|
||
** Function: ScConvert422PlanarTo411_C
|
||
** Purpose: Extract the Y, U and V components from (4:2:2)
|
||
** planes and convert to 4:1:1 so,
|
||
** only copy every other line of the chrominance
|
||
*/
|
||
ScStatus_t ScConvert422PlanarTo411_C (u_char *RawImage,
|
||
u_char *Y, u_char *U, u_char *V,
|
||
int Width, int Height)
|
||
{
|
||
register int y;
|
||
const int HalfWidth=Width/2;
|
||
unsigned char *RY, *RU, *RV;
|
||
RY=RawImage;
|
||
RU=RY+(Width*Height);
|
||
RV=RU+(Width*Height/2);
|
||
|
||
Height=abs(Height);
|
||
memcpy(Y, RawImage, Width*Height);
|
||
for (y = Height/2; y > 0; y--)
|
||
{
|
||
memcpy(U, RU, HalfWidth);
|
||
memcpy(V, RV, HalfWidth);
|
||
U+=HalfWidth;
|
||
V+=HalfWidth;
|
||
RU+=Width; /* skip odd U and V lines */
|
||
RV+=Width;
|
||
}
|
||
return (NoErrors);
|
||
}
|
||
|
||
/*
|
||
** C versions of block-extraction routines. To be replaced by ASM
|
||
*/
|
||
void ScConvertSep422ToBlockYUV (u_char *RawImage, int bpp,
|
||
float *Comp1, float *Comp2, float *Comp3,
|
||
int Width, int Height)
|
||
{
|
||
int x,y;
|
||
int VertBlocks = abs(Height)/8;
|
||
int YBlocks = Width/8;
|
||
int UBlocks = Width/16;
|
||
int VBlocks = Width/16;
|
||
int ByteWidth = Width*2;
|
||
u_char *I1 = RawImage;
|
||
u_char *I2 = I1 + Width*abs(Height);
|
||
u_char *I3 = I2 + Width*abs(Height)/2;
|
||
float *C1 = Comp1, *C2 = Comp2, *C3 = Comp3;
|
||
|
||
for (y = 0 ; y < VertBlocks ; y++) {
|
||
for (x = 0 ; x < YBlocks ; x++)
|
||
sc_ExtractBlockNonInt(I1, &C1, ByteWidth, x, y);
|
||
for (x = 0 ; x < UBlocks ; x++)
|
||
sc_ExtractBlockNonInt(I2, &C2, ByteWidth, x, y);
|
||
for (x = 0 ; x < VBlocks ; x++)
|
||
sc_ExtractBlockNonInt(I3, &C3, ByteWidth, x, y);
|
||
}
|
||
}
|
||
|
||
void ScConvertGrayToBlock (u_char *RawImage, int bpp,
|
||
float *Comp1, int Width, int Height)
|
||
{
|
||
int x,y;
|
||
int VertBlocks = abs(Height)/8;
|
||
int YBlocks = Width/8;
|
||
int ByteWidth = Width;
|
||
u_char *I1 = RawImage;
|
||
float *C1 = Comp1;
|
||
|
||
for (y = 0 ; y < VertBlocks ; y++)
|
||
for (x = 0 ; x < YBlocks ; x++)
|
||
sc_ExtractBlockNonInt(I1, &C1, ByteWidth, x, y);
|
||
}
|
||
|
||
|
||
/*
|
||
** Function: ScSepYUVto422i_C
|
||
** Purpose: Convert a 4:1:1 YUV image in separate-component form to its
|
||
** equivalent interleaved 4:2:2 form.
|
||
*/
|
||
extern int ScSepYUVto422i_C(u_char *Y, u_char *U,
|
||
u_char *V, u_char *ImageOut,
|
||
u_int width, u_int height)
|
||
{
|
||
/* need C code for this */
|
||
return(0);
|
||
}
|
||
|
||
/*
|
||
** Function: ScConvert422PlanarTo422i_C
|
||
** Purpose: Convert a 4:2:2 YUV image in separate-component form to its
|
||
** equivalent interleaved 4:2:2 form.
|
||
*/
|
||
extern void ScConvert422PlanarTo422i_C(u_char *Y, u_char *Cb,
|
||
u_char *Cr, u_char *OutImage,
|
||
long width, long height)
|
||
{
|
||
int i, j;
|
||
height=abs(height);
|
||
width=width>>1;
|
||
for (i=0; i<height; i++)
|
||
{
|
||
/* Remember, pixels are 16 bit in interleaved YUV. That
|
||
** means the 4 bytes below represent two pixels so our
|
||
** loop should be for half the width.
|
||
*/
|
||
for (j=0; j<width; j++)
|
||
{
|
||
*OutImage++ = *Y++;
|
||
*OutImage++ = *Cb++;
|
||
*OutImage++ = *Y++;
|
||
*OutImage++ = *Cr++;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
** Function: ScConvert422iTo422s_C
|
||
** Purpose: Convert a 4:2:2 YUV interleaved to 4:2:2 planar.
|
||
*/
|
||
extern void ScConvert422iTo422s_C(u_char *InImage,
|
||
u_char *Y, u_char *U, u_char *V,
|
||
long width, long height)
|
||
{
|
||
int i, j;
|
||
height=abs(height);
|
||
width=width>>1;
|
||
for (i=0; i<height; i++)
|
||
{
|
||
/* Remember, pixels are 16 bit in interleaved YUV. That
|
||
** means the 4 bytes below represent two pixels so our
|
||
** loop should be for half the width.
|
||
*/
|
||
for (j=0; j<width; j++)
|
||
{
|
||
*Y++ = *InImage++;
|
||
*U++ = *InImage++;
|
||
*Y++ = *InImage++;
|
||
*V++ = *InImage++;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
** Function: ScConvert422iTo422sf_C
|
||
** Purpose: Convert a 4:2:2 YUV interleaved to 4:2:2 planar.
|
||
*/
|
||
extern void ScConvert422iTo422sf_C(u_char *InImage, int bpp,
|
||
float *Y, float *U, float *V,
|
||
long width, long height)
|
||
{
|
||
int i, j;
|
||
height=abs(height);
|
||
width=width>>1;
|
||
for (i=0; i<height; i++)
|
||
{
|
||
/* Remember, pixels are 16 bit in interleaved YUV. That
|
||
** means the 4 bytes below represent two pixels so our
|
||
** loop should be for half the width.
|
||
*/
|
||
for (j=0; j<width; j++)
|
||
{
|
||
*Y++ = (float)*InImage++;
|
||
*U++ = (float)*InImage++;
|
||
*Y++ = (float)*InImage++;
|
||
*V++ = (float)*InImage++;
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
** Function: ScConvert411sTo422i_C
|
||
** Purpose: Convert a 4:1:1 YUV image in separate-component form to its
|
||
** equivalent interleaved 4:2:2 form.
|
||
*/
|
||
extern void ScConvert411sTo422i_C(u_char *Y, u_char *Cb,
|
||
u_char *Cr, u_char *OutImage,
|
||
long width, long height)
|
||
{
|
||
u_char *p422e, *p422o, *Yo=Y+width;
|
||
int i, j;
|
||
height=abs(height)/2;
|
||
p422e=OutImage;
|
||
p422o=OutImage+width*2;
|
||
|
||
for (i=0; i<height; i++)
|
||
{
|
||
for (j=0; j<width; j+=2)
|
||
{
|
||
*p422e++ = *Y++;
|
||
*p422e++ = *Cb;
|
||
*p422e++ = *Y++;
|
||
*p422e++ = *Cr;
|
||
*p422o++ = *Yo++;
|
||
*p422o++ = *Cb++;
|
||
*p422o++ = *Yo++;
|
||
*p422o++ = *Cr++;
|
||
}
|
||
p422e=p422o;
|
||
p422o=p422e+width*2;
|
||
Y=Yo;
|
||
Yo=Y+width;
|
||
}
|
||
}
|
||
|
||
/*
|
||
** Function: ScConvert411sTo422s_C
|
||
** Purpose: Convert a 4:1:1 YUV image in separate-component form to its
|
||
** equivalent interleaved 4:2:2 form.
|
||
*/
|
||
extern void ScConvert411sTo422s_C(u_char *Y, u_char *Cb,
|
||
u_char *Cr, u_char *OutImage,
|
||
long width, long height)
|
||
{
|
||
u_char *p411, *p422e, *p422o;
|
||
int i, j;
|
||
height=abs(height);
|
||
|
||
if (OutImage!=Y)
|
||
memcpy(OutImage, Y, width*height); /* copy Y components */
|
||
p411=Cb+((height/2)-1)*(width/2);
|
||
p422e=OutImage+((height*width*3)/2)-width; /* U component */
|
||
p422o=p422e+(width/2);
|
||
for (i=0; i<height; i+=2)
|
||
{
|
||
for (j=0; j<width; j+=2, p411++, p422e++, p422o++)
|
||
*p422e=*p422o=*p411;
|
||
p411-=width;
|
||
p422o=p422e-width;
|
||
p422e=p422o-(width/2);
|
||
}
|
||
p411=Cr+((height/2)-1)*(width/2);
|
||
p422e=OutImage+(height*width*2)-width; /* V component */
|
||
p422o=p422e+(width/2);
|
||
for (i=0; i<height; i+=2)
|
||
{
|
||
for (j=0; j<width; j+=2, p411++, p422e++, p422o++)
|
||
*p422e=*p422o=*p411;
|
||
p411-=width;
|
||
p422o=p422e-width;
|
||
p422e=p422o-(width/2);
|
||
}
|
||
}
|
||
|
||
/*
|
||
** Name: ScConvert1611sTo411s_C
|
||
** Purpose: convert a YCrCb 16:1:1 (YUV9/YVU9) to YCrCb 4:1:1
|
||
*/
|
||
ScStatus_t ScConvert1611sTo411s_C (u_char *inimage,
|
||
u_char *Y, u_char *U, u_char *V,
|
||
int Width, int Height)
|
||
{
|
||
register int y;
|
||
const int HalfWidth=Width/2;
|
||
unsigned char *RU, *RV;
|
||
int pixels = Width * abs(Height), tmp;
|
||
|
||
tmp = pixels / 16;
|
||
RU=inimage+pixels;
|
||
RV=RU+tmp;
|
||
|
||
memcpy(Y, inimage, pixels);
|
||
for (y = 0; y < tmp; y++)
|
||
{
|
||
*U++ = *RU;
|
||
*U++ = *RU;
|
||
*U++ = *RU;
|
||
*U++ = *RU++;
|
||
*V++ = *RV;
|
||
*V++ = *RV;
|
||
*V++ = *RV;
|
||
*V++ = *RV++;
|
||
}
|
||
return (NoErrors);
|
||
}
|
||
|
||
/*
|
||
** Name: ScConvert1611sTo422s_C
|
||
** Purpose: convert a YCrCb 16:1:1 (YUV9/YVU9) to YCrCb 4:2:2
|
||
*/
|
||
ScStatus_t ScConvert1611sTo422s_C(u_char *inimage,
|
||
u_char *Y, u_char *U, u_char *V,
|
||
int Width, int Height)
|
||
{
|
||
register int x, y;
|
||
const int HalfWidth=Width/2;
|
||
unsigned char *RU, *RV;
|
||
unsigned char *Uo, *Vo;
|
||
int pixels = Width * abs(Height), tmp;
|
||
|
||
tmp = pixels / 16;
|
||
RU=inimage+pixels;
|
||
RV=RU+tmp;
|
||
|
||
memcpy(Y, inimage, pixels);
|
||
for (y = Height/32; y>0; y--)
|
||
{
|
||
Vo=V+Width;
|
||
Uo=U+Width;
|
||
for (x = Width/4; x > 0; x--)
|
||
{
|
||
*U++ = *Uo++ = *RU;
|
||
*U++ = *Uo++ = *RU;
|
||
*U++ = *Uo++ = *RU;
|
||
*U++ = *Uo++ = *RU++;
|
||
*V++ = *Vo++ = *RV;
|
||
*V++ = *Vo++ = *RV;
|
||
*V++ = *Vo++ = *RV;
|
||
*V++ = *Vo++ = *RV++;
|
||
}
|
||
V=Vo; U=Uo;
|
||
}
|
||
return (NoErrors);
|
||
}
|
||
|
||
/*
|
||
** Name: ScConvert1611sTo422i_C
|
||
** Purpose: convert a YCrCb 16:1:1 (YUV9/YVU9) to 4:2:2 interleaved
|
||
*/
|
||
ScStatus_t ScConvert1611sTo422i_C(u_char *inimage, u_char *outimage,
|
||
int Width, int Height)
|
||
{
|
||
register int x, y;
|
||
const int HalfWidth=Width/2;
|
||
unsigned char *Ye, *Yo, *Ye2, *Yo2, *RU, *RV;
|
||
unsigned char *o1, *e1, *o2, *e2;
|
||
unsigned char U, V;
|
||
|
||
RU=inimage+Width*abs(Height);
|
||
RV=RU+(Width*abs(Height))/16;
|
||
|
||
e1=outimage;
|
||
Ye=inimage;
|
||
for (y = abs(Height)/4; y>0; y--)
|
||
{
|
||
Yo=Ye+Width;
|
||
Ye2=Yo+Width;
|
||
Yo2=Ye2+Width;
|
||
o1=e1+Width*2;
|
||
e2=o1+Width*2;
|
||
o2=e2+Width*2;
|
||
for (x = Width/4; x > 0; x--)
|
||
{
|
||
U = *RU++;
|
||
V = *RV++;
|
||
/* even line */
|
||
*e1++ = *Ye++;
|
||
*e1++ = U;
|
||
*e1++ = *Ye++;
|
||
*e1++ = V;
|
||
*e1++ = *Ye++;
|
||
*e1++ = U;
|
||
*e1++ = *Ye++;
|
||
*e1++ = V;
|
||
/* odd line */
|
||
*o1++ = *Yo++;
|
||
*o1++ = U;
|
||
*o1++ = *Yo++;
|
||
*o1++ = V;
|
||
*o1++ = *Yo++;
|
||
*o1++ = U;
|
||
*o1++ = *Yo++;
|
||
*o1++ = V;
|
||
/* even line */
|
||
*e2++ = *Ye2++;
|
||
*e2++ = U;
|
||
*e2++ = *Ye2++;
|
||
*e2++ = V;
|
||
*e2++ = *Ye2++;
|
||
*e2++ = U;
|
||
*e2++ = *Ye2++;
|
||
*e2++ = V;
|
||
/* odd line */
|
||
*o2++ = *Yo2++;
|
||
*o2++ = U;
|
||
*o2++ = *Yo2++;
|
||
*o2++ = V;
|
||
*o2++ = *Yo2++;
|
||
*o2++ = U;
|
||
*o2++ = *Yo2++;
|
||
*o2++ = V;
|
||
}
|
||
e1=o2;
|
||
Ye=Yo2;
|
||
}
|
||
return (NoErrors);
|
||
}
|
||
|
||
/*
|
||
** Name: ScConvert411sTo1611s_C
|
||
** Purpose: convert a YCrCb 4:1:1 to YCrCb 16:1:1 (YUV9/YVU9)
|
||
*/
|
||
ScStatus_t ScConvert411sTo1611s_C (u_char *inimage,
|
||
u_char *Y, u_char *U, u_char *V,
|
||
int Width, int Height)
|
||
{
|
||
register int x, y, c0, c1, c2, c3;
|
||
unsigned char *Ue, *Uo, *Ve, *Vo;
|
||
int pixels = Width * abs(Height), tmp;
|
||
Width/=2;
|
||
tmp = pixels / 4;
|
||
Ue=inimage+pixels;
|
||
Uo=Ue+Width;
|
||
Ve=Ue+tmp;
|
||
Vo=Ve+Width;
|
||
|
||
memcpy(Y, inimage, pixels);
|
||
for (y = 0; y < tmp; y+=2)
|
||
{
|
||
for (x=0; x<Width; x+=2)
|
||
{
|
||
c0=*Ue++;
|
||
c1=*Ue++;
|
||
c2=*Uo++;
|
||
c3=*Uo++;
|
||
*U++ = (c0+c1+c2+c3)/4;
|
||
}
|
||
Ue=Uo;
|
||
Uo+=Width;
|
||
}
|
||
for (y = 0; y < tmp; y+=2)
|
||
{
|
||
for (x=0; x<Width; x+=2)
|
||
{
|
||
c0=*Ve++;
|
||
c1=*Ve++;
|
||
c2=*Vo++;
|
||
c3=*Vo++;
|
||
*V++ = (c0+c1+c2+c3)/4;
|
||
}
|
||
Ve=Vo;
|
||
Vo+=Width;
|
||
}
|
||
return (NoErrors);
|
||
}
|
||
|
||
/*
|
||
** Function: ScConvertNTSCtoCIF422()
|
||
** Purpose: Convert a Q/CIF frame from a 4:2:2 NTSC input. We dup every 10th
|
||
** pixel horizontally and every 4th line vertically. We also
|
||
** discard the chroma on every other line, since CIF wants 4:1:1.
|
||
*/
|
||
ScStatus_t ScConvertNTSC422toCIF411_C(u_char *framein,
|
||
u_char *yp, u_char *up, u_char *vp,
|
||
int stride)
|
||
{
|
||
int h, w;
|
||
|
||
int vdup = 5;
|
||
for (h = 0; h < 240; ++h)
|
||
{
|
||
int hdup = 10/2;
|
||
for (w = 320; w > 0; w -= 2)
|
||
{
|
||
yp[0] = framein[0];
|
||
yp[1] = framein[2];
|
||
yp += 2;
|
||
if ((h & 1) == 0)
|
||
{
|
||
*up++ = framein[1];
|
||
*vp++ = framein[3];
|
||
}
|
||
framein += 4;
|
||
if (--hdup <= 0)
|
||
{
|
||
hdup = 10/2;
|
||
yp[0] = yp[-1];
|
||
yp += 1;
|
||
if ((h & 1) == 0)
|
||
{
|
||
if ((w & 2) == 0)
|
||
{
|
||
up[0] = up[-1];
|
||
++up;
|
||
vp[0] = vp[-1];
|
||
++vp;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (--vdup <= 0)
|
||
{
|
||
vdup = 5;
|
||
/* copy previous line */
|
||
memcpy((char*)yp, (char*)yp - stride, stride);
|
||
yp += stride;
|
||
if ((h & 1) == 0)
|
||
{
|
||
int s = stride >> 1;
|
||
memcpy((char*)up, (char*)up - s, s);
|
||
memcpy((char*)vp, (char*)vp - s, s);
|
||
up += s;
|
||
vp += s;
|
||
}
|
||
}
|
||
}
|
||
return (NoErrors);
|
||
}
|
||
|