/* * Microsoft YUV Codec UyVy -> rgb conversion functions * * Copyright (c) Microsoft Corporation 1993 * All Rights Reserved * */ #include #include #include #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; } }