Windows2003-3790/enduser/netmeeting/av/codecs/dec/dech261/sc_conv.c
2020-09-30 16:53:55 +02:00

2535 lines
79 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @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);
}