1467 lines
46 KiB
C
1467 lines
46 KiB
C
|
/*
|
||
|
* Microsoft YUV Codec UyVy -> rgb conversion functions
|
||
|
*
|
||
|
* Copyright (c) Microsoft Corporation 1993
|
||
|
* All Rights Reserved
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <windowsx.h>
|
||
|
#include <mmsystem.h>
|
||
|
|
||
|
#include "msyuv.h"
|
||
|
|
||
|
|
||
|
#include "rgb8lut.h" // can only be included once
|
||
|
|
||
|
/*
|
||
|
* This module provides translation from YUV into RGB. It translates
|
||
|
* from 8-bit YUV 4:2:2 (as provided by the Spigot video capture driver)
|
||
|
* or 7-bit YUV 4:1:1 (as provided by the Bravado driver) into 16-bit RGB555
|
||
|
* or RGB565. All versions use a look-up table built using YUVToRGB555
|
||
|
* or YUVToRGB565
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
#define RANGE(x, lo, hi) max(lo, min(hi, x))
|
||
|
|
||
|
/*
|
||
|
* Convert a YUV colour into a 15-bit RGB colour.
|
||
|
*
|
||
|
* The input Y is in the range 16..235; the input U and V components
|
||
|
* are in the range -128..+127. The conversion equations for this are
|
||
|
* (according to CCIR 601):
|
||
|
*
|
||
|
* R = Y + 1.371 V
|
||
|
* G = Y - 0.698 V - 0.336 U
|
||
|
* B = Y + 1.732 U
|
||
|
*
|
||
|
* To avoid floating point, we scale all values by 1024.
|
||
|
*
|
||
|
* The resulting RGB values are in the range 16..235: we truncate these to
|
||
|
* 5 bits each. and return a WORD containing 5-bits each for R, G and B
|
||
|
* with bit 15 set to 0.
|
||
|
*/
|
||
|
WORD
|
||
|
YUVToRGB555(int y, int u, int v)
|
||
|
{
|
||
|
int ScaledY = RANGE(y, 16, 235) * 1024;
|
||
|
int red, green, blue;
|
||
|
|
||
|
red = RANGE((ScaledY + (1404 * v)) / 1024, 0, 255);
|
||
|
green = RANGE((ScaledY - ( 715 * v) - (344 * u)) / 1024, 0, 255);
|
||
|
blue = RANGE((ScaledY + (1774 * u)) / 1024, 0, 255);
|
||
|
|
||
|
return (WORD) (((red & 0xf8) << 7) | ((green & 0xf8) << 2) | ((blue & 0xf8) >>3) );
|
||
|
}
|
||
|
|
||
|
|
||
|
// same as above but converts to RGB565 instead
|
||
|
WORD
|
||
|
YUVToRGB565(int y, int u, int v)
|
||
|
{
|
||
|
int ScaledY = RANGE(y, 16, 235) * 1024;
|
||
|
int red, green, blue;
|
||
|
|
||
|
red = RANGE((ScaledY + (1404 * v)) / 1024, 0, 255);
|
||
|
green = RANGE((ScaledY - ( 715 * v) - (344 * u)) / 1024, 0, 255);
|
||
|
blue = RANGE((ScaledY + (1774 * u)) / 1024, 0, 255);
|
||
|
|
||
|
return (WORD) (((red & 0xf8) << 8) | ((green & 0xfc) << 3) | ((blue & 0xf8) >>3) );
|
||
|
}
|
||
|
|
||
|
/* YUV 4:2:2 support ------------------------------------------ */
|
||
|
|
||
|
/*
|
||
|
* The captured data is in YUV 4:2:2, 8-bits per sample.
|
||
|
* The data is laid out in alternating Y-U-Y-V-Y-U-Y-V format. Thus
|
||
|
* every DWORD contains two complete pixels, in the
|
||
|
* form (msb..lsb) V..Y1..U..Y0
|
||
|
* All 3 components (y, u and v) are all unsigned 8-bit values in the range
|
||
|
* 16..235.
|
||
|
*
|
||
|
* We have to double scan lines for >= 480 line formats since
|
||
|
* the hardware only captured one field maximum.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
LPVOID BuildUYVYToRGB32( PINSTINFO pinst )
|
||
|
{
|
||
|
LPVOID pXlate;
|
||
|
long y, u, v;
|
||
|
|
||
|
// need 5 lookup tables to do the conversions, each is 256 entries long,
|
||
|
// and each contains short words.
|
||
|
//
|
||
|
short * yip; // Y impact
|
||
|
short * vrip; // red's V impact
|
||
|
short * vgip; // green's V impact
|
||
|
short * ugip; // green's U impact
|
||
|
short * ubip; // blue's U impact
|
||
|
|
||
|
dprintf2((TEXT("In BuildUYVYToRGB32\n")));
|
||
|
|
||
|
if (pinst->pXlate != NULL) {
|
||
|
return(pinst->pXlate);
|
||
|
}
|
||
|
|
||
|
dprintf1((TEXT("Allocate memory and building table for BuildUYVYToRGB32\n")));
|
||
|
|
||
|
/*
|
||
|
* allocate a table big enough for 5 256-byte arrays
|
||
|
*/
|
||
|
pXlate = VirtualAlloc (NULL, 5 * 256 * sizeof( short ), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||
|
|
||
|
if(!pXlate)
|
||
|
return pXlate;
|
||
|
|
||
|
// set the table offsets
|
||
|
//
|
||
|
yip = pXlate;
|
||
|
vrip = yip + 256;
|
||
|
vgip = vrip + 256;
|
||
|
ugip = vgip + 256;
|
||
|
ubip = ugip + 256;
|
||
|
|
||
|
// setup Y impact, etc
|
||
|
//
|
||
|
for( y = 0 ; y < 256 ; y++ )
|
||
|
{
|
||
|
yip[y] = (short)( ( 1.164 * ( y - 16L ) / 1.0 ) + 0 );
|
||
|
}
|
||
|
for( v = 0 ; v < 256 ; v++ )
|
||
|
{
|
||
|
vrip[v] = (short)( 1.596 * ( v - 128L ) / 1.0 );
|
||
|
vgip[v] = (short)( -0.813 * ( v - 128L ) / 1.0 );
|
||
|
}
|
||
|
for( u = 0 ; u < 256 ; u++ )
|
||
|
{
|
||
|
ugip[u] = (short)( -0.391 * ( u - 128L ) / 1.0 );
|
||
|
ubip[u] = (short)( 2.018 * ( u - 128L ) / 1.0 );
|
||
|
}
|
||
|
|
||
|
return(pXlate);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* build a translation table to translate between YUV and RGB555.
|
||
|
*
|
||
|
* This builds a lookup table with 32k 1-word entries: truncate the YUV
|
||
|
* to 15bits (5-5-5) and look-up in this xlate table to produce the
|
||
|
* 15-bit rgb value.
|
||
|
*/
|
||
|
LPVOID BuildUYVYToRGB555(PINSTINFO pinst)
|
||
|
{
|
||
|
LPVOID pXlate;
|
||
|
LPWORD pRGB555;
|
||
|
WORD w;
|
||
|
|
||
|
dprintf2((TEXT("In BuildUYVYToRGB555\n")));
|
||
|
|
||
|
if (pinst->pXlate != NULL) {
|
||
|
return(pinst->pXlate);
|
||
|
}
|
||
|
|
||
|
dprintf2((TEXT("Allocate memory and building table for BuildUYVYToRGB555\n")));
|
||
|
|
||
|
/*
|
||
|
* allocate a table big enough for 32k 2-byte entries
|
||
|
*/
|
||
|
pXlate = VirtualAlloc (NULL, 2 * 32 * 1024, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||
|
|
||
|
if(!pXlate)
|
||
|
return pXlate;
|
||
|
|
||
|
pRGB555 = (LPWORD)pXlate;
|
||
|
|
||
|
/*
|
||
|
* build a 15-bit yuv lookup table by stepping through each entry,
|
||
|
* converting the yuv index to rgb and storing at that index. The index
|
||
|
* to this table is a 15-bit value with the y component in bits 14..10,
|
||
|
* u in bits 9..5 and v in bits 4..0. Note that the y component is unsigned,
|
||
|
* whereas the u and v components are signed.
|
||
|
*/
|
||
|
for (w = 0; w < 32*1024; w++) {
|
||
|
|
||
|
/*
|
||
|
* the YUVtoRGB55 conversion function takes values 0..255 for y,
|
||
|
* and -128..+127 for u and v. Pick out the relevant bits of the
|
||
|
* index for this cell, and shift to get values in this range.
|
||
|
* Subtract 128 from u and v to shift from 0..255 to -128..+127
|
||
|
*/
|
||
|
*pRGB555++ = YUVToRGB555(
|
||
|
(w & 0x7c00) >> 7,
|
||
|
((w & 0x3e0) >> 2) - 128,
|
||
|
((w & 0x1f) << 3) - 128
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
return(pXlate);
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* build a translation table to translate between YUV and RGB 5-6-5
|
||
|
*
|
||
|
* This builds a lookup table with 32k 1-word entries: truncate the YUV
|
||
|
* to 15bits (5-5-5) and look-up in this xlate table to produce the
|
||
|
* 16-bit rgb value.
|
||
|
*/
|
||
|
LPVOID BuildUYVYToRGB565(PINSTINFO pinst)
|
||
|
{
|
||
|
LPVOID pXlate;
|
||
|
LPWORD pRGB;
|
||
|
WORD w;
|
||
|
|
||
|
dprintf2((TEXT("In BuildUYVYToRGB565\n")));
|
||
|
|
||
|
if (pinst->pXlate != NULL) {
|
||
|
return(pinst->pXlate);
|
||
|
}
|
||
|
|
||
|
dprintf2((TEXT("Allocate memory and building table for BuildUYVYToRGB565\n")));
|
||
|
|
||
|
/*
|
||
|
* allocate a table big enough for 32k 2-byte entries
|
||
|
*/
|
||
|
pXlate = VirtualAlloc (NULL, 2 * 32 * 1024, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||
|
|
||
|
|
||
|
if(!pXlate)
|
||
|
return pXlate;
|
||
|
|
||
|
pRGB = (LPWORD)pXlate;
|
||
|
|
||
|
/*
|
||
|
* build a 15-bit yuv lookup table by stepping through each entry,
|
||
|
* converting the yuv index to rgb and storing at that index. The index
|
||
|
* to this table is a 15-bit value with the y component in bits 14..10,
|
||
|
* u in bits 9..5 and v in bits 4..0. Note that the y component is unsigned,
|
||
|
* whereas the u and v components are signed.
|
||
|
*/
|
||
|
for (w = 0; w < 32*1024; w++) {
|
||
|
|
||
|
/*
|
||
|
* the YUVtoRGB conversion function takes values 0..255 for y,
|
||
|
* and -128..+127 for u and v. Pick out the relevant bits of the
|
||
|
* index for this cell, and shift to get values in this range.
|
||
|
* Subtract 128 from u and v to shift from 0..255 to -128..+127
|
||
|
*/
|
||
|
*pRGB++ = YUVToRGB565(
|
||
|
(w & 0x7c00) >> 7,
|
||
|
((w & 0x3e0) >> 2) - 128,
|
||
|
((w & 0x1f) << 3) - 128
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
return(pXlate);
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* build a translation table to translate between YUV and RGB8
|
||
|
*
|
||
|
*/
|
||
|
LPVOID BuildUYVYToRGB8(PINSTINFO pinst)
|
||
|
{
|
||
|
dprintf2((TEXT("In BuildUYVYToRGB8: no dynamically built table. Return NULL;\n")));
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* translate YUV 4:2:2 into 16-bit RGB using a lookup table. Flip vertically
|
||
|
* into DIB format during processing. Double scanlines for formats of
|
||
|
* 480 lines or greater. Produces 565 or 555 format RGB depending on the
|
||
|
* xlate table.
|
||
|
*/
|
||
|
VOID
|
||
|
UYVYToRGB16(
|
||
|
PINSTINFO pinst,
|
||
|
LPBITMAPINFOHEADER lpbiInput,
|
||
|
LPVOID lpInput,
|
||
|
LPBITMAPINFOHEADER lpbiOutput,
|
||
|
LPVOID lpOutput
|
||
|
)
|
||
|
{
|
||
|
int RowInc;
|
||
|
int i, j;
|
||
|
DWORD uv55, dwPixel;
|
||
|
int WidthBytes; // width of one line in BYTES
|
||
|
BOOL bDuplicate = FALSE;
|
||
|
PDWORD pSrc, pDst;
|
||
|
int Height, Width;
|
||
|
PWORD pXlate;
|
||
|
int InputHeight;
|
||
|
|
||
|
|
||
|
|
||
|
Height = abs(lpbiInput->biHeight);
|
||
|
InputHeight = Height;
|
||
|
Width = lpbiInput->biWidth;
|
||
|
|
||
|
WidthBytes = Width * 2 ;
|
||
|
ASSERT(lpbiInput->biBitCount / 8 == 2);
|
||
|
|
||
|
pXlate = pinst->pXlate;
|
||
|
|
||
|
pSrc = (PDWORD) lpInput;
|
||
|
|
||
|
dprintf3(("UYVYToRGB: %s %dx%d; %s %dx%dx%d=%d; %s %dx%dx%d=%d\n",
|
||
|
pinst->bRGB565?"RGB565" : "RGB555",
|
||
|
Width, Height,
|
||
|
(PCHAR) &lpbiInput->biCompression,
|
||
|
lpbiInput->biWidth, lpbiInput->biHeight, lpbiInput->biBitCount, lpbiInput->biSizeImage,
|
||
|
lpbiOutput->biCompression == 0 ? "RGB": lpbiOutput->biCompression == BI_BITFIELDS ? "BITF" : (PCHAR) &lpbiOutput->biCompression,
|
||
|
lpbiOutput->biWidth, lpbiOutput->biHeight, lpbiOutput->biBitCount, lpbiOutput->biSizeImage));
|
||
|
|
||
|
|
||
|
ASSERT((lpbiOutput->biWidth == lpbiInput->biWidth) && abs(lpbiOutput->biHeight) == abs(lpbiInput->biHeight));
|
||
|
|
||
|
/*
|
||
|
* calculate the amount to adjust pDst by at the end of one line
|
||
|
* of copying. At this point we are at the end of line N. We need
|
||
|
* to move to the start of line N-1.
|
||
|
*/
|
||
|
RowInc = WidthBytes * 2; // two lines!!
|
||
|
|
||
|
|
||
|
/* remember we are adding to a DWORD pointer */
|
||
|
RowInc /= sizeof(DWORD);
|
||
|
|
||
|
|
||
|
if(lpbiOutput->biCompression == FOURCC_UYVY ||
|
||
|
lpbiOutput->biCompression == FOURCC_YUY2 ||
|
||
|
lpbiOutput->biCompression == FOURCC_YVYU ) {
|
||
|
|
||
|
pDst = (PDWORD) lpOutput;
|
||
|
memcpy(pDst, pSrc, Width * Height * lpbiInput->biBitCount / 8); // Top down
|
||
|
|
||
|
} else {
|
||
|
|
||
|
// Output BI_RGB or BI_BITFIELD
|
||
|
// UVYV->RGB; +RGB->Flip
|
||
|
|
||
|
if(lpbiOutput->biHeight >= 0)
|
||
|
pDst = (PDWORD) ( (LPBYTE)lpOutput + (Height - 1) * WidthBytes );
|
||
|
else
|
||
|
pDst = (PDWORD) lpOutput;
|
||
|
|
||
|
|
||
|
//
|
||
|
// UyVy
|
||
|
//
|
||
|
if(pinst->dwFormat == FOURCC_UYVY) {
|
||
|
|
||
|
/* loop copying each scanline */
|
||
|
for (i = InputHeight; i > 0; i--) {
|
||
|
|
||
|
/* loop copying two pixels at a time */
|
||
|
for (j = Width ; j > 0; j -= 2) {
|
||
|
|
||
|
/*
|
||
|
* get two pixels and convert to 15-bpp YUV
|
||
|
*/
|
||
|
|
||
|
dwPixel = *pSrc++;
|
||
|
|
||
|
/*
|
||
|
* Convert UYVY (0x y1 V y0 U) to YUYV (0x V y1 U y0) in which the translation table is built for.
|
||
|
*/
|
||
|
#if defined(_X86_)
|
||
|
|
||
|
_asm {
|
||
|
// FourCC
|
||
|
// dwPixel 0x y1 V y0 U U0 Y0 V0 Y1
|
||
|
mov eax, dwPixel // 0x y1 V y0 U U0 Y0 V0 Y1
|
||
|
bswap eax // 0x U y0 V y1 Y1 V0 Y0 U0
|
||
|
rol eax, 16 // 0x V y1 U y0 Y0 U0 Y1 V0
|
||
|
mov dwPixel, eax
|
||
|
}
|
||
|
#else
|
||
|
|
||
|
dwPixel = (((dwPixel & 0xff00ff00) >> 8) | ((dwPixel & 0x00ff00ff) << 8));
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* dwPixel now has two pixels, in this layout (MSB..LSB):
|
||
|
*
|
||
|
* V Y1 U Y0
|
||
|
*
|
||
|
* convert to 2 yuv555 words and lookup in xlate table
|
||
|
*/
|
||
|
|
||
|
/* get common u and v components to lower 10 bits */ // 9 8 7 6 5 4 3 2 1 0
|
||
|
uv55 = ((dwPixel & 0xf8000000) >> 27) | ((dwPixel & 0x0000f800) >> 6); // U7U6:U5U4U3 V7:V6V5V4V3
|
||
|
|
||
|
|
||
|
/* build each yuv-655 value by truncating
|
||
|
* y to 5 bits and adding the common u and v bits,
|
||
|
* look up to convert to rgb, and combine two pixels
|
||
|
* into one dword
|
||
|
*/ // f e d c b a 9 8 7 6 5 4 3 2 1 0
|
||
|
dwPixel = pXlate[((dwPixel & 0x000000f8) << 7) | uv55 ] | // 0Y7Y6Y5:Y4Y3 U7U6:U5U4U3 V7:V6V5V4V3
|
||
|
(pXlate[((dwPixel & 0x00f80000) >> 9) | uv55 ] << 16); // 0Y7Y6Y5:Y4Y3 U7U6:U5U4U3 V7:V6V5V4V3
|
||
|
|
||
|
/* write two pixels to destination */
|
||
|
*pDst++ = dwPixel;
|
||
|
|
||
|
} // loop per 2 pixels
|
||
|
|
||
|
|
||
|
/*
|
||
|
* bottom up need re-adjust its pointer by
|
||
|
* moving dest pointer back to next line
|
||
|
*/
|
||
|
|
||
|
if(lpbiOutput->biHeight >= 0) {
|
||
|
pDst -= RowInc;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// yUyV
|
||
|
//
|
||
|
} else if(pinst->dwFormat == FOURCC_YUY2) {
|
||
|
|
||
|
/* loop copying each scanline */
|
||
|
for (i = InputHeight; i > 0; i--) {
|
||
|
|
||
|
/* loop copying two pixels at a time */
|
||
|
for (j = Width ; j > 0; j -= 2) {
|
||
|
|
||
|
/*
|
||
|
* get two pixels and convert to 15-bpp YUV
|
||
|
*/
|
||
|
|
||
|
dwPixel = *pSrc++;
|
||
|
|
||
|
// We are already in YUYV (0x V y1 U y0) format.
|
||
|
|
||
|
/* get common u and v components to lower 10 bits */ // 9 8 7 6 5 4 3 2 1 0
|
||
|
uv55 = ((dwPixel & 0xf8000000) >> 27) | ((dwPixel & 0x0000f800) >> 6); // U7U6:U5U4U3 V7:V6V5V4V3
|
||
|
|
||
|
|
||
|
/* build each yuv-655 value by truncating
|
||
|
* y to 5 bits and adding the common u and v bits,
|
||
|
* look up to convert to rgb, and combine two pixels
|
||
|
* into one dword
|
||
|
*/ // f e d c b a 9 8 7 6 5 4 3 2 1 0
|
||
|
dwPixel = pXlate[((dwPixel & 0x000000f8) << 7) | uv55 ] | // 0Y7Y6Y5:Y4Y3 U7U6:U5U4U3 V7:V6V5V4V3
|
||
|
(pXlate[((dwPixel & 0x00f80000) >> 9) | uv55 ] << 16); // 0Y7Y6Y5:Y4Y3 U7U6:U5U4U3 V7:V6V5V4V3
|
||
|
|
||
|
/* write two pixels to destination */
|
||
|
*pDst++ = dwPixel;
|
||
|
|
||
|
} // loop per 2 pixels
|
||
|
|
||
|
|
||
|
/*
|
||
|
* bottom up need re-adjust its pointer by
|
||
|
* moving dest pointer back to next line
|
||
|
*/
|
||
|
|
||
|
if(lpbiOutput->biHeight >= 0) {
|
||
|
pDst -= RowInc;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// yVyU
|
||
|
//
|
||
|
} else if(pinst->dwFormat == FOURCC_YVYU) {
|
||
|
/* loop copying each scanline */
|
||
|
for (i = InputHeight; i > 0; i--) {
|
||
|
|
||
|
/* loop copying two pixels at a time */
|
||
|
for (j = Width ; j > 0; j -= 2) {
|
||
|
|
||
|
/*
|
||
|
* get two pixels and convert to 15-bpp YUV
|
||
|
*/
|
||
|
|
||
|
dwPixel = *pSrc++;
|
||
|
|
||
|
/*
|
||
|
* Convert yVyU (0x U y1 V y0) to YUYV (0x V y1 U y0) in which the translation table is built for.
|
||
|
*/
|
||
|
#if defined(_X86_)
|
||
|
|
||
|
_asm {
|
||
|
// FourCC
|
||
|
// dwPixel 0x U y1 V y0
|
||
|
mov eax, dwPixel // 0x U y1 V y0
|
||
|
bswap eax // 0x y0 V y1 U
|
||
|
rol eax, 8 // 0x V y1 U y0
|
||
|
mov dwPixel, eax
|
||
|
}
|
||
|
#else
|
||
|
// y0 and y1 stay and swap U and V
|
||
|
dwPixel = (dwPixel & 0x00ff00ff) | ((dwPixel & 0x0000ff00) << 16) | ((dwPixel & 0xff000000) >> 16);
|
||
|
#endif
|
||
|
|
||
|
/* get common u and v components to lower 10 bits */ // 9 8 7 6 5 4 3 2 1 0
|
||
|
uv55 = ((dwPixel & 0xf8000000) >> 27) | ((dwPixel & 0x0000f800) >> 6); // U7U6:U5U4U3 V7:V6V5V4V3
|
||
|
|
||
|
|
||
|
/* build each yuv-655 value by truncating
|
||
|
* y to 5 bits and adding the common u and v bits,
|
||
|
* look up to convert to rgb, and combine two pixels
|
||
|
* into one dword
|
||
|
*/ // f e d c b a 9 8 7 6 5 4 3 2 1 0
|
||
|
dwPixel = pXlate[((dwPixel & 0x000000f8) << 7) | uv55 ] | // 0Y7Y6Y5:Y4Y3 U7U6:U5U4U3 V7:V6V5V4V3
|
||
|
(pXlate[((dwPixel & 0x00f80000) >> 9) | uv55 ] << 16); // 0Y7Y6Y5:Y4Y3 U7U6:U5U4U3 V7:V6V5V4V3
|
||
|
|
||
|
/* write two pixels to destination */
|
||
|
*pDst++ = dwPixel;
|
||
|
|
||
|
} // loop per 2 pixels
|
||
|
|
||
|
|
||
|
/*
|
||
|
* bottom up need re-adjust its pointer by
|
||
|
* moving dest pointer back to next line
|
||
|
*/
|
||
|
|
||
|
if(lpbiOutput->biHeight >= 0) {
|
||
|
pDst -= RowInc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* translate YUV 4:2:2 into 8-bit RGB using a lookup table.
|
||
|
* i.e. 0x Y1:V:Y0:U -> ox index1;index0
|
||
|
*/
|
||
|
VOID
|
||
|
UYVYToRGB8(
|
||
|
PINSTINFO pinst,
|
||
|
LPBITMAPINFOHEADER lpbiInput,
|
||
|
LPVOID lpInput,
|
||
|
LPBITMAPINFOHEADER lpbiOutput,
|
||
|
LPVOID lpOutput
|
||
|
)
|
||
|
{
|
||
|
register dwPixel;
|
||
|
int i, j;
|
||
|
int SrcRawInc, DstRawInc, Dst3RawInc;
|
||
|
PDWORD pSrc, pSrc1; // Every 32bit UYVY
|
||
|
PWORD pDst, pDst1; // Convert to two 8bit RGB8
|
||
|
int Height, Width;
|
||
|
int InputHeight;
|
||
|
unsigned char y0, y1, y2, y3,
|
||
|
u0, u1,
|
||
|
v0, v1;
|
||
|
unsigned long yuv0, yuv1;
|
||
|
|
||
|
|
||
|
Height = abs(lpbiInput->biHeight);
|
||
|
InputHeight = Height;
|
||
|
Width = lpbiInput->biWidth;
|
||
|
|
||
|
|
||
|
dprintf3(("UYVYToRGB8: %dx%d; %s %dx%dx%d=%d; %s %dx%dx%d=%d\n",
|
||
|
Width, Height,
|
||
|
(PCHAR) &lpbiInput->biCompression,
|
||
|
lpbiInput->biWidth, lpbiInput->biHeight, lpbiInput->biBitCount, lpbiInput->biSizeImage,
|
||
|
lpbiOutput->biCompression == 0 ? "RGB": lpbiOutput->biCompression == BI_BITFIELDS ? "BITF" : (PCHAR) &lpbiOutput->biCompression,
|
||
|
lpbiOutput->biWidth, lpbiOutput->biHeight, lpbiOutput->biBitCount, lpbiOutput->biSizeImage));
|
||
|
|
||
|
ASSERT(lpbiInput->biBitCount == 16 && lpbiOutput->biBitCount == 8);
|
||
|
ASSERT((lpbiOutput->biWidth == lpbiInput->biWidth) && abs(lpbiOutput->biHeight) == abs(lpbiInput->biHeight));
|
||
|
ASSERT(( lpbiOutput->biWidth % 8 == 0 )); // Align with pairs of UYVY:UYVY
|
||
|
ASSERT(( lpbiOutput->biHeight % 2 == 0 )); // Even number of lines
|
||
|
|
||
|
|
||
|
/*
|
||
|
* calculate the amount to adjust pDst by at the end of one line of copying.
|
||
|
*/
|
||
|
|
||
|
// 2bytes per pixel; pSrc is PDWORD
|
||
|
SrcRawInc = Width * 2 / sizeof(DWORD);
|
||
|
|
||
|
// 1 byte per pixel; pDst is PWORD
|
||
|
DstRawInc = Width * 1 / sizeof(WORD);
|
||
|
Dst3RawInc = 3 * DstRawInc;
|
||
|
|
||
|
pSrc = (PDWORD) lpInput;
|
||
|
pSrc1 = pSrc + SrcRawInc;
|
||
|
|
||
|
// UVYV->RGB8; same sign:flip.
|
||
|
|
||
|
if(lpbiOutput->biHeight >= 0) {
|
||
|
|
||
|
pDst = (PWORD) ( (LPBYTE)lpOutput + (Height - 1) * Width/sizeof(BYTE) );
|
||
|
pDst1 = (PWORD) ( (LPBYTE)lpOutput + (Height - 2) * Width/sizeof(BYTE) );
|
||
|
} else {
|
||
|
pDst = (PWORD) lpOutput;
|
||
|
pDst1 = (PWORD) ((LPBYTE)lpOutput+Width/sizeof(BYTE));
|
||
|
}
|
||
|
|
||
|
if(pinst->dwFormat == FOURCC_UYVY) {
|
||
|
|
||
|
// loop copying two scanline
|
||
|
for (i = InputHeight; i > 0; i -= 2) {
|
||
|
// loop copying four (% 8) pixels at a time
|
||
|
for (j = Width ; j > 0; j -= 4) {
|
||
|
|
||
|
//
|
||
|
// Translate TopLeft, TopRight
|
||
|
//
|
||
|
|
||
|
dwPixel = *pSrc++;
|
||
|
// Pixel is in this format: Y1:V:Y0:U
|
||
|
y0 = (dwPixel & 0x0000ff00) >> 8;
|
||
|
y1 = (dwPixel & 0xff000000) >> 24;
|
||
|
u0 = (dwPixel & 0x000000ff);
|
||
|
v0 = (dwPixel & 0x00ff0000) >> 16;
|
||
|
|
||
|
dwPixel = *pSrc++;
|
||
|
y2 = (dwPixel & 0x0000ff00) >> 8;
|
||
|
y3 = (dwPixel & 0xff000000) >> 24;
|
||
|
u1 = (dwPixel & 0x000000ff);
|
||
|
v1 = (dwPixel & 0x00ff0000) >> 16;
|
||
|
|
||
|
yuv0 = yLUT_1[y1+2] | yLUT_0[y0+10] | cLUT_B0[u0] | cLUT_R0[v0];
|
||
|
yuv1 = yLUT_1[y3+0] | yLUT_0[y2+8] | cLUT_B0[u1+4] | cLUT_R0[v1+4];
|
||
|
|
||
|
*pDst++ = (WORD) yuv0;
|
||
|
*pDst++ = (WORD) yuv1;
|
||
|
|
||
|
//
|
||
|
// Translate BottomLeft, BottomRight
|
||
|
//
|
||
|
|
||
|
dwPixel = *pSrc1++;
|
||
|
// Pixel is in this format: Y1:V:Y0:U
|
||
|
y0 = (dwPixel & 0x0000ff00) >> 8;
|
||
|
y1 = (dwPixel & 0xff000000) >> 24;
|
||
|
u0 = (dwPixel & 0x000000ff);
|
||
|
v0 = (dwPixel & 0x00ff0000) >> 16;
|
||
|
|
||
|
dwPixel = *pSrc1++;
|
||
|
y2 = (dwPixel & 0x0000ff00) >> 8;
|
||
|
y3 = (dwPixel & 0xff000000) >> 24;
|
||
|
u1 = (dwPixel & 0x000000ff);
|
||
|
v1 = (dwPixel & 0x00ff0000) >> 16;
|
||
|
|
||
|
yuv0 = yLUT_1[y1+0] | yLUT_0[y0+8] | cLUT_B0[u0+4] | cLUT_R0[v0+4];
|
||
|
yuv1 = yLUT_1[y3+2] | yLUT_0[y2+10] | cLUT_B0[u1+0] | cLUT_R0[v1+0];
|
||
|
|
||
|
*pDst1++ = (WORD) yuv0;
|
||
|
*pDst1++ = (WORD) yuv1;
|
||
|
|
||
|
} // 2 * 4 pixel per loops
|
||
|
|
||
|
|
||
|
/*
|
||
|
* bottom up need re-adjust its pointer by
|
||
|
* moving dest pointer back to next line
|
||
|
*/
|
||
|
if (lpbiOutput->biHeight >= 0) {
|
||
|
|
||
|
pDst -= Dst3RawInc;
|
||
|
pDst1 -= Dst3RawInc;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
pDst += DstRawInc;
|
||
|
pDst1 += DstRawInc;
|
||
|
}
|
||
|
|
||
|
pSrc += SrcRawInc;
|
||
|
pSrc1 += SrcRawInc;
|
||
|
|
||
|
} // 2 lines per loop
|
||
|
} else if(pinst->dwFormat == FOURCC_YUY2) { // YUY2
|
||
|
|
||
|
// loop copying two scanline
|
||
|
for (i = InputHeight; i > 0; i -= 2) {
|
||
|
// loop copying four (% 8) pixels at a time
|
||
|
for (j = Width ; j > 0; j -= 4) {
|
||
|
|
||
|
//
|
||
|
// Translate TopLeft, TopRight
|
||
|
//
|
||
|
|
||
|
dwPixel = *pSrc++;
|
||
|
// Pixel is in this format: V:Y1:U:Y0
|
||
|
u0 = (dwPixel & 0x0000ff00) >> 8;
|
||
|
v0 = (dwPixel & 0xff000000) >> 24;
|
||
|
y0 = (dwPixel & 0x000000ff);
|
||
|
y1 = (dwPixel & 0x00ff0000) >> 16;
|
||
|
|
||
|
dwPixel = *pSrc++;
|
||
|
u1 = (dwPixel & 0x0000ff00) >> 8;
|
||
|
v1 = (dwPixel & 0xff000000) >> 24;
|
||
|
y2 = (dwPixel & 0x000000ff);
|
||
|
y3 = (dwPixel & 0x00ff0000) >> 16;
|
||
|
|
||
|
yuv0 = yLUT_1[y1+2] | yLUT_0[y0+10] | cLUT_B0[u0] | cLUT_R0[v0];
|
||
|
yuv1 = yLUT_1[y3+0] | yLUT_0[y2+8] | cLUT_B0[u1+4] | cLUT_R0[v1+4];
|
||
|
|
||
|
*pDst++ = (WORD) yuv0;
|
||
|
*pDst++ = (WORD) yuv1;
|
||
|
|
||
|
//
|
||
|
// Translate BottomLeft, BottomRight
|
||
|
//
|
||
|
|
||
|
dwPixel = *pSrc1++;
|
||
|
// Pixel is in this format: V:Y1:U:Y0
|
||
|
u0 = (dwPixel & 0x0000ff00) >> 8;
|
||
|
v0 = (dwPixel & 0xff000000) >> 24;
|
||
|
y0 = (dwPixel & 0x000000ff);
|
||
|
y1 = (dwPixel & 0x00ff0000) >> 16;
|
||
|
|
||
|
dwPixel = *pSrc1++;
|
||
|
u1 = (dwPixel & 0x0000ff00) >> 8;
|
||
|
v1 = (dwPixel & 0xff000000) >> 24;
|
||
|
y2 = (dwPixel & 0x000000ff);
|
||
|
y3 = (dwPixel & 0x00ff0000) >> 16;
|
||
|
|
||
|
yuv0 = yLUT_1[y1+0] | yLUT_0[y0+8] | cLUT_B0[u0+4] | cLUT_R0[v0+4];
|
||
|
yuv1 = yLUT_1[y3+2] | yLUT_0[y2+10] | cLUT_B0[u1+0] | cLUT_R0[v1+0];
|
||
|
|
||
|
*pDst1++ = (WORD) yuv0;
|
||
|
*pDst1++ = (WORD) yuv1;
|
||
|
|
||
|
} // 2 * 4 pixel per loops
|
||
|
|
||
|
|
||
|
/*
|
||
|
* bottom up need re-adjust its pointer by
|
||
|
* moving dest pointer back to next line
|
||
|
*/
|
||
|
if (lpbiOutput->biHeight >= 0) {
|
||
|
|
||
|
pDst -= Dst3RawInc;
|
||
|
pDst1 -= Dst3RawInc;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
pDst += DstRawInc;
|
||
|
pDst1 += DstRawInc;
|
||
|
}
|
||
|
|
||
|
pSrc += SrcRawInc;
|
||
|
pSrc1 += SrcRawInc;
|
||
|
|
||
|
} // 2 lines per loop
|
||
|
|
||
|
|
||
|
} else if(pinst->dwFormat == FOURCC_YVYU) {
|
||
|
// loop copying two scanline
|
||
|
for (i = InputHeight; i > 0; i -= 2) {
|
||
|
// loop copying four (% 8) pixels at a time
|
||
|
for (j = Width ; j > 0; j -= 4) {
|
||
|
|
||
|
//
|
||
|
// Translate TopLeft, TopRight
|
||
|
//
|
||
|
|
||
|
dwPixel = *pSrc++;
|
||
|
// Pixel is in this format: U:Y1:V:Y0
|
||
|
v0 = (dwPixel & 0x0000ff00) >> 8;
|
||
|
u0 = (dwPixel & 0xff000000) >> 24;
|
||
|
y0 = (dwPixel & 0x000000ff);
|
||
|
y1 = (dwPixel & 0x00ff0000) >> 16;
|
||
|
|
||
|
dwPixel = *pSrc++;
|
||
|
v1 = (dwPixel & 0x0000ff00) >> 8;
|
||
|
u1 = (dwPixel & 0xff000000) >> 24;
|
||
|
y2 = (dwPixel & 0x000000ff);
|
||
|
y3 = (dwPixel & 0x00ff0000) >> 16;
|
||
|
|
||
|
yuv0 = yLUT_1[y1+2] | yLUT_0[y0+10] | cLUT_B0[u0] | cLUT_R0[v0];
|
||
|
yuv1 = yLUT_1[y3+0] | yLUT_0[y2+8] | cLUT_B0[u1+4] | cLUT_R0[v1+4];
|
||
|
|
||
|
*pDst++ = (WORD) yuv0;
|
||
|
*pDst++ = (WORD) yuv1;
|
||
|
|
||
|
//
|
||
|
// Translate BottomLeft, BottomRight
|
||
|
//
|
||
|
|
||
|
dwPixel = *pSrc1++;
|
||
|
// Pixel is in this format: U:Y1:V:Y0
|
||
|
v0 = (dwPixel & 0x0000ff00) >> 8;
|
||
|
u0 = (dwPixel & 0xff000000) >> 24;
|
||
|
y0 = (dwPixel & 0x000000ff);
|
||
|
y1 = (dwPixel & 0x00ff0000) >> 16;
|
||
|
|
||
|
dwPixel = *pSrc1++;
|
||
|
v1 = (dwPixel & 0x0000ff00) >> 8;
|
||
|
u1 = (dwPixel & 0xff000000) >> 24;
|
||
|
y2 = (dwPixel & 0x000000ff);
|
||
|
y3 = (dwPixel & 0x00ff0000) >> 16;
|
||
|
|
||
|
yuv0 = yLUT_1[y1+0] | yLUT_0[y0+8] | cLUT_B0[u0+4] | cLUT_R0[v0+4];
|
||
|
yuv1 = yLUT_1[y3+2] | yLUT_0[y2+10] | cLUT_B0[u1+0] | cLUT_R0[v1+0];
|
||
|
|
||
|
*pDst1++ = (WORD) yuv0;
|
||
|
*pDst1++ = (WORD) yuv1;
|
||
|
|
||
|
} // 2 * 4 pixel per loops
|
||
|
|
||
|
|
||
|
/*
|
||
|
* bottom up need re-adjust its pointer by
|
||
|
* moving dest pointer back to next line
|
||
|
*/
|
||
|
if (lpbiOutput->biHeight >= 0) {
|
||
|
|
||
|
pDst -= Dst3RawInc;
|
||
|
pDst1 -= Dst3RawInc;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
pDst += DstRawInc;
|
||
|
pDst1 += DstRawInc;
|
||
|
}
|
||
|
|
||
|
pSrc += SrcRawInc;
|
||
|
pSrc1 += SrcRawInc;
|
||
|
|
||
|
} // 2 lines per loop
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
UYVYToRGB32(
|
||
|
PINSTINFO pinst,
|
||
|
LPBITMAPINFOHEADER lpbiInput,
|
||
|
LPVOID lpInput,
|
||
|
LPBITMAPINFOHEADER lpbiOutput,
|
||
|
LPVOID lpOutput
|
||
|
)
|
||
|
{
|
||
|
int Height = abs( lpbiInput->biHeight );
|
||
|
int Width = lpbiInput->biWidth;
|
||
|
short U;
|
||
|
short V;
|
||
|
short y0, y1;
|
||
|
short d;
|
||
|
DWORD * pSrc = lpInput;
|
||
|
BYTE * pDst = lpOutput;
|
||
|
long WidthBytes = Width * 4; // ARGB = 4 bytes
|
||
|
int i, j;
|
||
|
DWORD dwYUV;
|
||
|
long l;
|
||
|
|
||
|
// set up the lookup table arrays
|
||
|
//
|
||
|
short * yip = pinst->pXlate;
|
||
|
short * vrip = yip + 256;
|
||
|
short * vgip = vrip + 256;
|
||
|
short * ugip = vgip + 256;
|
||
|
short * ubip = ugip + 256;
|
||
|
|
||
|
// if just a straight copy
|
||
|
//
|
||
|
if(lpbiOutput->biCompression == FOURCC_UYVY ||
|
||
|
lpbiOutput->biCompression == FOURCC_YUY2 ||
|
||
|
lpbiOutput->biCompression == FOURCC_YVYU )
|
||
|
{
|
||
|
memcpy( pDst, pSrc, WidthBytes * Height ); // Top down
|
||
|
return;
|
||
|
|
||
|
}
|
||
|
|
||
|
// flip around if necessary
|
||
|
//
|
||
|
if(lpbiOutput->biHeight >= 0)
|
||
|
{
|
||
|
pDst += (Height - 1) * WidthBytes;
|
||
|
}
|
||
|
|
||
|
if( pinst->dwFormat == FOURCC_UYVY ) // U0 Y0 V0 Y1 U2 Y2 V2 Y3
|
||
|
{
|
||
|
for (i = Height; i > 0; i--)
|
||
|
{
|
||
|
/* loop copying two pixels at a time */
|
||
|
for (j = Width ; j > 0; j -= 2)
|
||
|
{
|
||
|
// get two YUV pixels at a time
|
||
|
//
|
||
|
dwYUV = *pSrc++; // U0 Y0 V0 Y1
|
||
|
U = (short) ( dwYUV & 0xFF );
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
y0 = yip[( dwYUV & 0xFF )];
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
V = (short) ( dwYUV & 0xFF );
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
y1 = yip[( dwYUV & 0xFF )];
|
||
|
|
||
|
d = y0 + ubip[U]; // blue
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y0 + ugip[U] + vgip[V]; // green
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y0 + vrip[V]; // red
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
pDst++;
|
||
|
|
||
|
d = y1 + ubip[U]; // blue
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y1 + ugip[U] + vgip[V]; // green
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y1 + vrip[V]; // red
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
pDst++;
|
||
|
} // for j
|
||
|
|
||
|
// back up two rows to get to the next scanline
|
||
|
//
|
||
|
if(lpbiOutput->biHeight >= 0)
|
||
|
{
|
||
|
pDst -= WidthBytes * 2;
|
||
|
}
|
||
|
} // for i
|
||
|
} // UYVY
|
||
|
else if( pinst->dwFormat == FOURCC_YUY2 ) // Y0 U0 Y1 V0...
|
||
|
{
|
||
|
for (i = Height; i > 0; i--)
|
||
|
{
|
||
|
/* loop copying two pixels at a time */
|
||
|
for (j = Width ; j > 0; j -= 2)
|
||
|
{
|
||
|
// We are already in YUYV (0x V y1 U y0) format.
|
||
|
|
||
|
#if 0 // straight computation
|
||
|
// get two YUV pixels at a time
|
||
|
//
|
||
|
dwYUV = *pSrc++; // Y0 U0 Y1 V0
|
||
|
y0 = (short) ( dwYUV & 0xFF ) - 16;
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
U = (short) ( dwYUV & 0xFF ) - 128;
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
y1 = (short) ( dwYUV & 0xFF ) - 16;
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
V = (short) ( dwYUV & 0xFF ) - 128;
|
||
|
|
||
|
l = ( ( y0 * 298L ) + ( 517L * U ) ) / 256; // blue
|
||
|
if( l < 0 ) l = 0;
|
||
|
if( l > 255 ) l = 255;
|
||
|
*pDst++ = (BYTE) l; // blue
|
||
|
l = ( ( y0 * 298L ) - ( 100L * U ) - ( 208L * V ) ) / 256; // green
|
||
|
if( l < 0 ) l = 0;
|
||
|
if( l > 255 ) l = 255;
|
||
|
*pDst++ = (BYTE) l; // green
|
||
|
l = ( ( y0 * 298L ) + ( 409L * V ) ) / 256; // red
|
||
|
if( l < 0 ) l = 0;
|
||
|
if( l > 255 ) l = 255;
|
||
|
*pDst++ = (BYTE) l; // red
|
||
|
pDst++;
|
||
|
|
||
|
l = ( ( y1 * 298L ) + ( 517L * U ) ) / 256; // blue
|
||
|
if( l < 0 ) l = 0;
|
||
|
if( l > 255 ) l = 255;
|
||
|
*pDst++ = (BYTE) l; // blue
|
||
|
l = ( ( y1 * 298L ) - ( 100L * U ) - ( 208L * V ) ) / 256; // green
|
||
|
if( l < 0 ) l = 0;
|
||
|
if( l > 255 ) l = 255;
|
||
|
*pDst++ = (BYTE) l; // green
|
||
|
l = ( ( y1 * 298L ) + ( 409L * V ) ) / 256; // red
|
||
|
if( l < 0 ) l = 0;
|
||
|
if( l > 255 ) l = 255;
|
||
|
*pDst++ = (BYTE) l; // red
|
||
|
pDst++;
|
||
|
|
||
|
#else // table lookup
|
||
|
// get two YUV pixels at a time
|
||
|
//
|
||
|
dwYUV = *pSrc++; // Y0 U0 Y1 V0
|
||
|
y0 = yip[( dwYUV & 0xFF )];
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
U = (short) ( dwYUV & 0xFF );
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
y1 = yip[( dwYUV & 0xFF )];
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
V = (short) ( dwYUV & 0xFF );
|
||
|
|
||
|
|
||
|
d = y0 + ubip[U]; // blue
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y0 + ugip[U] + vgip[V]; // green
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y0 + vrip[V]; // red
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
pDst++;
|
||
|
|
||
|
|
||
|
d = y1 + ubip[U]; // blue
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y1 + ugip[U] + vgip[V]; // green
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y1 + vrip[V]; // red
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
pDst++;
|
||
|
#endif
|
||
|
} // for j
|
||
|
|
||
|
// back up two rows to get to the next scanline
|
||
|
//
|
||
|
if(lpbiOutput->biHeight >= 0)
|
||
|
{
|
||
|
pDst -= WidthBytes * 2;
|
||
|
}
|
||
|
} // for i
|
||
|
}
|
||
|
else if( pinst->dwFormat == FOURCC_YVYU ) // Y0 V0 Y1 U0...
|
||
|
{
|
||
|
for (i = Height; i > 0; i--)
|
||
|
{
|
||
|
/* loop copying two pixels at a time */
|
||
|
for (j = Width ; j > 0; j -= 2)
|
||
|
{
|
||
|
// get two YUV pixels at a time
|
||
|
//
|
||
|
dwYUV = *pSrc++; // Y0 U0 Y1 V0
|
||
|
y0 = yip[( dwYUV & 0xFF )];
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
V = (short) ( dwYUV & 0xFF );
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
y1 = yip[( dwYUV & 0xFF )];
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
U = (short) ( dwYUV & 0xFF );
|
||
|
|
||
|
d = y0 + ubip[U]; // blue
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y0 + ugip[U] + vgip[V]; // green
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y0 + vrip[V]; // red
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
pDst++;
|
||
|
|
||
|
|
||
|
d = y1 + ubip[U]; // blue
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y1 + ugip[U] + vgip[V]; // green
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y1 + vrip[V]; // red
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
pDst++;
|
||
|
} // for j
|
||
|
|
||
|
// back up two rows to get to the next scanline
|
||
|
//
|
||
|
if(lpbiOutput->biHeight >= 0)
|
||
|
{
|
||
|
pDst -= WidthBytes * 2;
|
||
|
}
|
||
|
} // for i
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
UYVYToRGB24(
|
||
|
PINSTINFO pinst,
|
||
|
LPBITMAPINFOHEADER lpbiInput,
|
||
|
LPVOID lpInput,
|
||
|
LPBITMAPINFOHEADER lpbiOutput,
|
||
|
LPVOID lpOutput
|
||
|
)
|
||
|
{
|
||
|
int Height = abs( lpbiInput->biHeight );
|
||
|
int Width = lpbiInput->biWidth;
|
||
|
short U;
|
||
|
short V;
|
||
|
short y0, y1;
|
||
|
short d;
|
||
|
DWORD * pSrc = lpInput;
|
||
|
BYTE * pDst = lpOutput;
|
||
|
long WidthBytes = Width * 3; // RGB = 3 bytes
|
||
|
int i, j;
|
||
|
DWORD dwYUV;
|
||
|
long l;
|
||
|
short maxd = 0;
|
||
|
short mind = 255;
|
||
|
|
||
|
// set up the lookup table arrays
|
||
|
//
|
||
|
short * yip = pinst->pXlate;
|
||
|
short * vrip = yip + 256;
|
||
|
short * vgip = vrip + 256;
|
||
|
short * ugip = vgip + 256;
|
||
|
short * ubip = ugip + 256;
|
||
|
|
||
|
// if just a straight copy
|
||
|
//
|
||
|
if(lpbiOutput->biCompression == FOURCC_UYVY ||
|
||
|
lpbiOutput->biCompression == FOURCC_YUY2 ||
|
||
|
lpbiOutput->biCompression == FOURCC_YVYU )
|
||
|
{
|
||
|
memcpy( pDst, pSrc, WidthBytes * Height ); // Top down
|
||
|
return;
|
||
|
|
||
|
}
|
||
|
|
||
|
// flip around if necessary
|
||
|
//
|
||
|
if(lpbiOutput->biHeight >= 0)
|
||
|
{
|
||
|
pDst += (Height - 1) * WidthBytes;
|
||
|
}
|
||
|
|
||
|
if( pinst->dwFormat == FOURCC_UYVY ) // U0 Y0 V0 Y1 U2 Y2 V2 Y3
|
||
|
{
|
||
|
for (i = Height; i > 0; i--)
|
||
|
{
|
||
|
/* loop copying two pixels at a time */
|
||
|
for (j = Width ; j > 0; j -= 2)
|
||
|
{
|
||
|
// get two YUV pixels at a time
|
||
|
//
|
||
|
dwYUV = *pSrc++; // U0 Y0 V0 Y1
|
||
|
U = (short) ( dwYUV & 0xFF );
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
y0 = yip[( dwYUV & 0xFF )];
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
V = (short) ( dwYUV & 0xFF );
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
y1 = yip[( dwYUV & 0xFF )];
|
||
|
|
||
|
d = y0 + ubip[U]; // blue
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y0 + ugip[U] + vgip[V]; // green
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y0 + vrip[V]; // red
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
|
||
|
|
||
|
d = y1 + ubip[U]; // blue
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y1 + ugip[U] + vgip[V]; // green
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y1 + vrip[V]; // red
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
} // for j
|
||
|
|
||
|
// back up two rows to get to the next scanline
|
||
|
//
|
||
|
if(lpbiOutput->biHeight >= 0)
|
||
|
{
|
||
|
pDst -= WidthBytes * 2;
|
||
|
}
|
||
|
} // for i
|
||
|
} // UYVY
|
||
|
else if( pinst->dwFormat == FOURCC_YUY2 ) // Y0 U0 Y1 V0...
|
||
|
{
|
||
|
for (i = Height; i > 0; i--)
|
||
|
{
|
||
|
/* loop copying two pixels at a time */
|
||
|
for (j = Width ; j > 0; j -= 2)
|
||
|
{
|
||
|
// We are already in YUYV (0x V y1 U y0) format.
|
||
|
|
||
|
#if 0 // straight computation
|
||
|
// get two YUV pixels at a time
|
||
|
//
|
||
|
dwYUV = *pSrc++; // Y0 U0 Y1 V0
|
||
|
y0 = (short) ( dwYUV & 0xFF ) - 16;
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
U = (short) ( dwYUV & 0xFF ) - 128;
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
y1 = (short) ( dwYUV & 0xFF ) - 16;
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
V = (short) ( dwYUV & 0xFF ) - 128;
|
||
|
|
||
|
l = ( ( y0 * 298L ) + ( 517L * U ) ) / 256; // blue
|
||
|
if( l < 0 ) l = 0;
|
||
|
if( l > 255 ) l = 255;
|
||
|
*pDst++ = (BYTE) l; // blue
|
||
|
l = ( ( y0 * 298L ) - ( 100L * U ) - ( 208L * V ) ) / 256; // green
|
||
|
if( l < 0 ) l = 0;
|
||
|
if( l > 255 ) l = 255;
|
||
|
*pDst++ = (BYTE) l; // green
|
||
|
l = ( ( y0 * 298L ) + ( 409L * V ) ) / 256; // red
|
||
|
if( l < 0 ) l = 0;
|
||
|
if( l > 255 ) l = 255;
|
||
|
*pDst++ = (BYTE) l; // red
|
||
|
l = ( ( y1 * 298L ) + ( 517L * U ) ) / 256; // blue
|
||
|
if( l < 0 ) l = 0;
|
||
|
if( l > 255 ) l = 255;
|
||
|
*pDst++ = (BYTE) l; // blue
|
||
|
l = ( ( y1 * 298L ) - ( 100L * U ) - ( 208L * V ) ) / 256; // green
|
||
|
if( l < 0 ) l = 0;
|
||
|
if( l > 255 ) l = 255;
|
||
|
*pDst++ = (BYTE) l; // green
|
||
|
l = ( ( y1 * 298L ) + ( 409L * V ) ) / 256; // red
|
||
|
if( l < 0 ) l = 0;
|
||
|
if( l > 255 ) l = 255;
|
||
|
*pDst++ = (BYTE) l; // red
|
||
|
#else // table lookup
|
||
|
// get two YUV pixels at a time
|
||
|
//
|
||
|
dwYUV = *pSrc++; // Y0 U0 Y1 V0
|
||
|
y0 = yip[( dwYUV & 0xFF )];
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
U = (short) ( dwYUV & 0xFF );
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
y1 = yip[( dwYUV & 0xFF )];
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
V = (short) ( dwYUV & 0xFF );
|
||
|
|
||
|
|
||
|
d = y0 + ubip[U]; // blue
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y0 + ugip[U] + vgip[V]; // green
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y0 + vrip[V]; // red
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
|
||
|
|
||
|
d = y1 + ubip[U]; // blue
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y1 + ugip[U] + vgip[V]; // green
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y1 + vrip[V]; // red
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
#endif
|
||
|
} // for j
|
||
|
|
||
|
// back up two rows to get to the next scanline
|
||
|
//
|
||
|
if(lpbiOutput->biHeight >= 0)
|
||
|
{
|
||
|
pDst -= WidthBytes * 2;
|
||
|
}
|
||
|
} // for i
|
||
|
}
|
||
|
else if( pinst->dwFormat == FOURCC_YVYU ) // Y0 V0 Y1 U0...
|
||
|
{
|
||
|
for (i = Height; i > 0; i--)
|
||
|
{
|
||
|
/* loop copying two pixels at a time */
|
||
|
for (j = Width ; j > 0; j -= 2)
|
||
|
{
|
||
|
// get two YUV pixels at a time
|
||
|
//
|
||
|
dwYUV = *pSrc++; // Y0 U0 Y1 V0
|
||
|
y0 = yip[( dwYUV & 0xFF )];
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
V = (short) ( dwYUV & 0xFF );
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
y1 = yip[( dwYUV & 0xFF )];
|
||
|
dwYUV = dwYUV >> 8;
|
||
|
U = (short) ( dwYUV & 0xFF );
|
||
|
|
||
|
d = y0 + ubip[U]; // blue
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y0 + ugip[U] + vgip[V]; // green
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y0 + vrip[V]; // red
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
|
||
|
d = y1 + ubip[U]; // blue
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y1 + ugip[U] + vgip[V]; // green
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
d = y1 + vrip[V]; // red
|
||
|
if( d < 0 ) d = 0;
|
||
|
if( d > 255 ) d = 255;
|
||
|
*pDst++ = (BYTE) d;
|
||
|
} // for j
|
||
|
|
||
|
// back up two rows to get to the next scanline
|
||
|
//
|
||
|
if(lpbiOutput->biHeight >= 0)
|
||
|
{
|
||
|
pDst -= WidthBytes * 2;
|
||
|
}
|
||
|
} // for i
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
#define OFFSET 10
|
||
|
#define STDPALCOLOURS 256
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* DecompressGetPalette() implements ICM_GET_PALETTE
|
||
|
*
|
||
|
* This function has no Compress...() equivalent
|
||
|
*
|
||
|
* It is used to pull the palette from a frame in order to possibly do
|
||
|
* a palette change.
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
DWORD NEAR PASCAL DecompressGetPalette(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
|
||
|
{
|
||
|
DWORD dw;
|
||
|
unsigned char * lpPalArea;
|
||
|
long Index, cntEntries;
|
||
|
HDC hDC;
|
||
|
|
||
|
PALETTEENTRY apeSystem[STDPALCOLOURS]; // OFFSET];
|
||
|
|
||
|
|
||
|
dprintf2((TEXT("DecompressGetPalette()\n")));
|
||
|
if (dw = DecompressQuery(pinst, lpbiIn, NULL))
|
||
|
return dw;
|
||
|
|
||
|
if (lpbiOut->biBitCount != 8) { /* 8-bit only for palettes */
|
||
|
dprintf1(("DecompressGetPalette: Unsupported lpbiOut->biBitCount=%d\n", lpbiOut->biBitCount));
|
||
|
return (DWORD)ICERR_ERROR;
|
||
|
}
|
||
|
|
||
|
// Initialise the palette entries in the header
|
||
|
|
||
|
dprintf1(("DecompressGetPalette(): in->biSize=%d, out->biSize=%d\n", lpbiIn->biSize, lpbiOut->biSize));
|
||
|
|
||
|
|
||
|
// Get the standard system colours
|
||
|
|
||
|
if ( hDC = GetDC(GetDesktopWindow()) )
|
||
|
{
|
||
|
cntEntries = GetSystemPaletteEntries(hDC,0,STDPALCOLOURS,apeSystem);
|
||
|
ReleaseDC(GetDesktopWindow(),hDC);
|
||
|
}
|
||
|
|
||
|
if (cntEntries == 0) {
|
||
|
dprintf2(("DecompressGetPalette:cntEntries is 0; GetSystemPaletteEntries failed.\n"));
|
||
|
|
||
|
lpbiOut->biClrUsed = 0;
|
||
|
lpbiOut->biClrImportant = 0;
|
||
|
return (DWORD) ICERR_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
lpbiOut->biClrUsed = STDPALCOLOURS;
|
||
|
lpbiOut->biClrImportant = 0;
|
||
|
|
||
|
// Adding system device colours to be dithered
|
||
|
lpPalArea = (unsigned char *)lpbiOut + (int)lpbiOut->biSize;
|
||
|
|
||
|
// Copy the first ten VGA system colours
|
||
|
|
||
|
for (Index = 0;Index < OFFSET;Index++) {
|
||
|
lpPalArea[Index*4+0] = apeSystem[Index].peRed;
|
||
|
lpPalArea[Index*4+1] = apeSystem[Index].peGreen;
|
||
|
lpPalArea[Index*4+2] = apeSystem[Index].peBlue;
|
||
|
lpPalArea[Index*4+3] = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Copy the palette we dither to one colour at a time
|
||
|
|
||
|
for (Index = OFFSET;Index < STDPALCOLOURS-OFFSET;Index++) {
|
||
|
lpPalArea[Index*4+0] = PalTable[Index*4+2];
|
||
|
lpPalArea[Index*4+1] = PalTable[Index*4+1];
|
||
|
lpPalArea[Index*4+2] = PalTable[Index*4+0];
|
||
|
lpPalArea[Index*4+3] = 0;
|
||
|
}
|
||
|
|
||
|
// Copy the last ten VGA system colours
|
||
|
|
||
|
for (Index = STDPALCOLOURS-OFFSET;Index < STDPALCOLOURS;Index++) {
|
||
|
lpPalArea[Index*4+0] = apeSystem[Index].peRed;
|
||
|
lpPalArea[Index*4+1] = apeSystem[Index].peGreen;
|
||
|
lpPalArea[Index*4+2] = apeSystem[Index].peBlue;
|
||
|
lpPalArea[Index*4+3] = 0;
|
||
|
}
|
||
|
|
||
|
return (DWORD)ICERR_OK;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID FreeXlate(PINSTINFO pinst)
|
||
|
{
|
||
|
|
||
|
ASSERT(pinst != NULL);
|
||
|
if (pinst && pinst->pXlate != NULL) {
|
||
|
VirtualFree(pinst->pXlate, 0, MEM_RELEASE);
|
||
|
pinst->pXlate = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|