www.pudn.com > LastTray_Jpeg.rar > BitmapFile.cpp
// MURUGAN@NDR (2002/05/16)
// CBitmapFile class cpp file implementation
// Functions to create a BMP/JPEG file from a window and desktop
#include "stdafx.h"
#include "BitmapFile.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#include "jpeglib.h"
#ifdef __cplusplus
}
#endif // __cplusplus
#include
struct ima_error_mgr
{
struct jpeg_error_mgr pub; // "public" fields
jmp_buf setjmp_buffer; // for return to caller
};
inline int Grey( int r, int g, int b )
{
return ((( b * 11 ) + ( g * 59 ) + ( r * 30 )) / 100 );
}
CBitmapFile::CBitmapFile()
{
}
CBitmapFile::~CBitmapFile()
{
}
BOOL CBitmapFile::SaveDesktopAsFile(CString strFileName,int nFileType,CPoint p1,CPoint p2,int tag)
{
CString strError = "";
CWnd* pWnd = CWnd::GetDesktopWindow();
CBitmap bitmap;
CWindowDC dc(pWnd);
CDC memDC;
CRect rect;
CDC *pDC; //屏幕DC
int Width = 0, Height = 0;
pDC=CDC::FromHandle(GetDC(NULL));
int BitPerPixel=pDC->GetDeviceCaps(BITSPIXEL);//获得颜色模式
Width = p2.x - p1.x;
Height = p2.y - p1.y;
memDC.CreateCompatibleDC(&dc);
pWnd->GetWindowRect(rect);
bitmap.CreateCompatibleBitmap(&dc, Width,Height);//rect.Width(),rect.Height() );
CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
memDC.BitBlt(0, 0, Width,Height, &dc, p1.x, p1.y, SRCCOPY);
// Create logical palette if device support a palette
CPalette pal;
if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE )
{
UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * 256);
LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
pLP->palVersion = 0x300;
pLP->palNumEntries =
GetSystemPaletteEntries( dc, 0, 255, pLP->palPalEntry );
// Create the palette
pal.CreatePalette( pLP );
delete[] pLP;
}
// Convert the bitmap to a DIB
HANDLE hDIB = DDBToDIB( bitmap, BI_RGB, &pal );
if( hDIB == NULL )
return FALSE;
memDC.SelectObject(pOldBitmap);
JpegFromDib(hDIB, 100, strFileName, &strError);
// Free the memory allocated by DDBToDIB for the DIB
GlobalFree( hDIB );
return TRUE;
}
BOOL CBitmapFile::SaveWindowAsFile(CString strFileName, CWnd *pWnd ,int nFileType,CPoint p1,CPoint p2)
{
CString strError = "";
CBitmap bitmap;
CWindowDC dc(pWnd);
CDC memDC;
CRect rect;
int Width = p2.x - p1.x;
int Height = p2.y - p1.y;
memDC.CreateCompatibleDC(&dc);
bitmap.CreateCompatibleBitmap(&dc, Width,Height );
CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
memDC.BitBlt(p1.x, p1.y, Width,Height, &dc, 0, 0, SRCCOPY);
// Create logical palette if device support a palette
CPalette pal;
if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE )
{
UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * 256);
LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
pLP->palVersion = 0x300;
pLP->palNumEntries =
GetSystemPaletteEntries( dc, 0, 255, pLP->palPalEntry );
// Create the palette
pal.CreatePalette( pLP );
delete[] pLP;
}
memDC.SelectObject(pOldBitmap);
// Convert the bitmap to a DIB
HANDLE hDIB = DDBToDIB( bitmap, BI_RGB, &pal );
if( hDIB == NULL )
return FALSE;
// Write it to file
JpegFromDib(hDIB, 100, strFileName, &strError);
// Free the memory allocated by DDBToDIB for the DIB
GlobalFree( hDIB );
return TRUE;
}
// DDBToDIB - Creates a DIB from a DDB
// bitmap - Device dependent bitmap
// dwCompression - Type of compression - see BITMAPINFOHEADER
// pPal - Logical palette
HANDLE CBitmapFile::DDBToDIB( CBitmap& bitmap, DWORD dwCompression, CPalette* pPal )
{
BITMAP bm;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
DWORD dwLen;
HANDLE hDIB;
HANDLE handle;
HDC hDC;
HPALETTE hPal;
ASSERT( bitmap.GetSafeHandle() );
// The function has no arg for bitfields
if( dwCompression == BI_BITFIELDS )
return NULL;
// If a palette has not been supplied use defaul palette
hPal = (HPALETTE) pPal->GetSafeHandle();
if (hPal==NULL)
hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
// Get bitmap information
bitmap.GetObject(sizeof(bm),(LPSTR)&bm);
// Initialize the bitmapinfoheader
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = bm.bmPlanes * bm.bmBitsPixel; //bm.bmPlanes * bm.bmBitsPixel;
bi.biCompression = dwCompression;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
// Compute the size of the infoheader and the color table
int nColors = (1 << bi.biBitCount);
if( nColors > 256 )
nColors = 0;
dwLen = bi.biSize + nColors * sizeof(RGBQUAD);
// We need a device context to get the DIB from
hDC = GetDC(NULL);
hPal = SelectPalette(hDC,hPal,FALSE);
RealizePalette(hDC);
// Allocate enough memory to hold bitmapinfoheader and color table
hDIB = GlobalAlloc(GMEM_FIXED,dwLen);
if (!hDIB){
SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return NULL;
}
lpbi = (LPBITMAPINFOHEADER)hDIB;
*lpbi = bi;
// Call GetDIBits with a NULL lpBits param, so the device driver
// will calculate the biSizeImage field
GetDIBits(hDC, (HBITMAP)bitmap.GetSafeHandle(), 0L, (DWORD)bi.biHeight,
(LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);
bi = *lpbi;
// If the driver did not fill in the biSizeImage field, then compute it
// Each scan line of the image is aligned on a DWORD (32bit) boundary
if (bi.biSizeImage == 0){
bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8)
* bi.biHeight;
// If a compression scheme is used the result may infact be larger
// Increase the size to account for this.
if (dwCompression != BI_RGB)
bi.biSizeImage = (bi.biSizeImage * 3) / 2;
}
// Realloc the buffer so that it can hold all the bits
dwLen += bi.biSizeImage;
if (handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE))
hDIB = handle;
else{
GlobalFree(hDIB);
// Reselect the original palette
SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return NULL;
}
// Get the bitmap bits
lpbi = (LPBITMAPINFOHEADER)hDIB;
// FINALLY get the DIB
BOOL bGotBits = GetDIBits( hDC, (HBITMAP)bitmap.GetSafeHandle(),
0L, // Start scan line
(DWORD)bi.biHeight, // # of scan lines
(LPBYTE)lpbi // address for bitmap bits
+ (bi.biSize + nColors * sizeof(RGBQUAD)),
(LPBITMAPINFO)lpbi, // address of bitmapinfo
(DWORD)DIB_RGB_COLORS); // Use RGB for color table
if( !bGotBits )
{
GlobalFree(hDIB);
SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return NULL;
}
SelectPalette(hDC,hPal,FALSE);
ReleaseDC(NULL,hDC);
return hDIB;
}
BOOL CBitmapFile::WriteDIB( LPTSTR szFile, HANDLE hDIB)
{
BITMAPFILEHEADER hdr;
LPBITMAPINFOHEADER lpbi;
if (!hDIB)
return FALSE;
CFile file;
if( !file.Open( szFile, CFile::modeWrite|CFile::modeCreate) )
return FALSE;
lpbi = (LPBITMAPINFOHEADER)hDIB;
int nColors = 1 << lpbi->biBitCount;
// Fill in the fields of the file header
hdr.bfType = ((WORD) ('M' << 8) | 'B'); // is always "BM"
hdr.bfSize = GlobalSize (hDIB) + sizeof( hdr );
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = (DWORD) (sizeof( hdr ) + lpbi->biSize +
nColors * sizeof(RGBQUAD));
// Write the file header
file.Write( &hdr, sizeof(hdr) );
// Write the DIB header and the bits
file.Write( lpbi, GlobalSize(hDIB) );
return TRUE;
}
// DrawGreyScale - Draws a bitmap in Grey scale
// pDC - Pointer to target device context
// hDIB - Handle of device-independent bitmap
//
void CBitmapFile::DrawGreyScale( CDC *pDC, HANDLE hDIB )
{
CPalette pal;
CPalette *pOldPalette = 0;
BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;
int nColors = bmInfo.bmiHeader.biClrUsed ? bmInfo.bmiHeader.biClrUsed :
1 << bmInfo.bmiHeader.biBitCount;
int nWidth = bmInfo.bmiHeader.biWidth;
int nHeight = bmInfo.bmiHeader.biHeight;
// Compute the address of the bitmap bits
LPVOID lpDIBBits;
if( bmInfo.bmiHeader.biBitCount > 8 )
lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors +
bmInfo.bmiHeader.biClrUsed) +
((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
else
lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors);
// Create the palette if needed
if( pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE && nColors <= 256 )
{
// The device supports a palette and bitmap has color table
// Allocate memory for a palette
UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
pLP->palVersion = 0x300;
pLP->palNumEntries = nColors;
for( int i=0; i < nColors; i++)
{
int nGrey = Grey( bmInfo.bmiColors[i].rgbRed, bmInfo.bmiColors[i].rgbGreen,
bmInfo.bmiColors[i].rgbBlue );
pLP->palPalEntry[i].peRed = nGrey;
pLP->palPalEntry[i].peGreen = nGrey;
pLP->palPalEntry[i].peBlue = nGrey;
pLP->palPalEntry[i].peFlags = 0;
}
pal.CreatePalette( pLP );
delete[] pLP;
// Select the palette
pOldPalette = pDC->SelectPalette(&pal, FALSE);
pDC->RealizePalette();
}
else if((pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE) == 0 && nColors <= 256 )
{
// Device does not supports palettes but bitmap has a color table
// Modify the bitmaps color table directly
// Note : This ends up changing the DIB. If that is not acceptable then
// copy the DIB and then change the copy rather than the original
for( int i=0; i < nColors; i++)
{
int nGrey = Grey( bmInfo.bmiColors[i].rgbRed, bmInfo.bmiColors[i].rgbGreen,
bmInfo.bmiColors[i].rgbBlue );
bmInfo.bmiColors[i].rgbRed = nGrey;
bmInfo.bmiColors[i].rgbGreen = nGrey;
bmInfo.bmiColors[i].rgbBlue = nGrey;
}
}
else
{
// Modify the bitmaps pixels directly
// Note : This ends up changing the DIB. If that is not acceptable then
// copy the DIB and then change the copy rather than the original
if ( bmInfo.bmiHeader.biBitCount == 24 )
{
BYTE *dst=(BYTE*)lpDIBBits;
int Size=nWidth*nHeight;
while ( Size-- )
{
int nGrey = Grey( dst[2], dst[1], dst[0] );
dst[0]=(BYTE)nGrey;
dst[1]=(BYTE)nGrey;
dst[2]=(BYTE)nGrey;
dst+=4;
}
}
else if ( bmInfo.bmiHeader.biBitCount == 16 )
{
WORD *dst=(WORD*)lpDIBBits;
int Size=nWidth*nHeight;
while ( Size-- )
{
BYTE b = (BYTE)((*dst)&(0x1F));
BYTE g = (BYTE)(((*dst)>>5)&(0x1F));
BYTE r = (BYTE)(((*dst)>>10)&(0x1F));
int nGrey = Grey( r, g, b );
*dst++ = ((WORD)(((BYTE)(nGrey)|((WORD)((BYTE)(nGrey))<<5))|(((DWORD)(BYTE)(nGrey))<<10)));
}
}
}
// Draw the image
::SetDIBitsToDevice(pDC->m_hDC, // hDC
0, // XDest
0, // YDest
nWidth, // nDestWidth
nHeight, // nDestHeight
0, // XSrc
0, // YSrc
0, // nStartScan
nHeight, // nNumScans
lpDIBBits, // lpBits
(LPBITMAPINFO)hDIB, // lpBitsInfo
DIB_RGB_COLORS); // wUsage
if ( pOldPalette )
pDC->SelectPalette(pOldPalette, FALSE);
}
////////////////////////////////////////////////////////////////////////////
//This function takes the contents of a DIB
//and turns it into a JPEG file.
//
//The DIB may be monochrome, 16-color, 256-color, or 24-bit color.
//
//Any functions or data items beginning with "jpeg_" belong to jpeg.lib,
//and are not included here.
//
//The function assumes 3 color components per pixel.
/////////////////////////////////////////////////////////////////////////////
BOOL CBitmapFile::JpegFromDib( HANDLE hDib, //Handle to DIB
int nQuality, //JPEG quality (0-100)
CString csJpeg, //Pathname to jpeg file
CString* pcsMsg) //Error msg to return
{
//Basic sanity checks...
if (nQuality < 0 || nQuality > 100 ||
hDib == NULL ||
pcsMsg == NULL ||
csJpeg == "")
{
if (pcsMsg != NULL)
*pcsMsg = "Invalid input data";
return FALSE;
}
*pcsMsg = "";
byte *buf2 = 0;
//Use libjpeg functions to write scanlines to disk in JPEG format
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE* pOutFile; //Target file
int nSampsPerRow; //Physical row width in image buffer
JSAMPARRAY jsmpArray; //Pixel RGB buffer for JPEG file
cinfo.err = jpeg_std_error(&jerr); //Use default error handling (ugly!)
jpeg_create_compress(&cinfo);
if ((pOutFile = fopen(csJpeg, "wb")) == NULL)
{
*pcsMsg = "Cannot open ";
*pcsMsg += csJpeg;
jpeg_destroy_compress(&cinfo);
return FALSE;
}
jpeg_stdio_dest(&cinfo, pOutFile);
LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)hDib;
cinfo.image_width = lpbi->biWidth; //Image width and height, in pixels
cinfo.image_height = lpbi->biHeight;
cinfo.input_components = 3; //Color components per pixel
//(RGB_PIXELSIZE - see jmorecfg.h)
cinfo.in_color_space = JCS_RGB; //Colorspace of input image
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo,
nQuality, //Quality: 0-100 scale
TRUE); //Limit to baseline-JPEG values
jpeg_start_compress(&cinfo, TRUE);
//JSAMPLEs per row in output buffer
nSampsPerRow = cinfo.image_width * cinfo.input_components;
//Allocate array of pixel RGB values
jsmpArray = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo,
JPOOL_IMAGE,
nSampsPerRow,
cinfo.image_height);
if (DibToSamps(hDib,
nSampsPerRow,
cinfo,
jsmpArray,
pcsMsg))
{
//Write the array of scan lines to the JPEG file
(void)jpeg_write_scanlines(&cinfo,
jsmpArray,
cinfo.image_height);
}
jpeg_finish_compress(&cinfo); //Always finish
fclose(pOutFile);
jpeg_destroy_compress(&cinfo); //Free resources
if (*pcsMsg != "")
return FALSE;
else
return TRUE;
}
////////////////////////////////////////////////////////////////
//This function fills a jsmpArray with the RGB values
//for the CBitmap.
//
//It has been improved to handle all legal bitmap formats.
//
//A jsmpArray is a big array of RGB values, 3 bytes per value.
//
//Note that rows of pixels are processed bottom to top:
//The data in the jsamp array must be arranged top to bottom.
////////////////////////////////////////////////////////////////
BOOL CBitmapFile::DibToSamps(HANDLE hDib,
int nSampsPerRow,
struct jpeg_compress_struct cinfo,
JSAMPARRAY jsmpPixels,
CString* pcsMsg)
{
//Sanity...
if (hDib == NULL ||
nSampsPerRow <= 0 || pcsMsg == NULL)
{
if (pcsMsg !=NULL)
*pcsMsg="Invalid input data";
return FALSE;
}
int r=0, p=0, q=0, b=0, n=0,
nUnused=0, nBytesWide=0, nUsed=0, nLastBits=0, nLastNibs=0, nCTEntries=0,
nRow=0, nByte=0, nPixel=0;
BYTE bytCTEnt=0;
LPBITMAPINFOHEADER pbBmHdr= (LPBITMAPINFOHEADER)hDib; //The bit count tells you the format of the bitmap: //Decide how many entries will be in the color table (if any)
switch (pbBmHdr->biBitCount)
{
case 1:
nCTEntries = 2; //Monochrome
break;
case 4:
nCTEntries = 16; //16-color
break;
case 8:
nCTEntries = 256; //256-color
break;
case 16:
case 24:
case 32:
nCTEntries = 0; //No color table needed
break;
default:
*pcsMsg = "Invalid bitmap bit count";
return FALSE; //Unsupported format
}
//Point to the color table and pixels
DWORD dwCTab = (DWORD)pbBmHdr + pbBmHdr->biSize;
LPRGBQUAD pCTab = (LPRGBQUAD)(dwCTab);
LPSTR lpBits = (LPSTR)pbBmHdr +
(WORD)pbBmHdr->biSize +
(WORD)(nCTEntries * sizeof(RGBQUAD));
//Different formats for the image bits
LPBYTE lpPixels = (LPBYTE) lpBits;
RGBQUAD* pRgbQs = (RGBQUAD*)lpBits;
WORD* wPixels = (WORD*) lpBits;
//Set up the jsamps according to the bitmap's format.
//Note that rows are processed bottom to top, because
//that's how bitmaps are created.
switch (pbBmHdr->biBitCount)
{
case 1:
nUsed = (pbBmHdr->biWidth + 7) / 8;
nUnused = (((nUsed + 3) / 4) * 4) - nUsed;
nBytesWide = nUsed + nUnused;
nLastBits = 8 - ((nUsed * 8) - pbBmHdr->biWidth);
for (r=0; r < pbBmHdr->biHeight; r++)
{
for (p=0, q=0; p < nUsed; p++)
{
nRow=(pbBmHdr->biHeight-r-1) * nBytesWide;
nByte = nRow + p;
int nBUsed = (p < (nUsed >> 1) ) ? 8 : nLastBits;
// ^^ Not sure about this symbol Might be problem
for(b=0; b < nBUsed;b++)
{
bytCTEnt = lpPixels[nByte] << b;
bytCTEnt = bytCTEnt >> 7;
jsmpPixels[r][q+0] = pCTab[bytCTEnt].rgbRed;
jsmpPixels[r][q+1] = pCTab[bytCTEnt].rgbGreen;
jsmpPixels[r][q+2] = pCTab[bytCTEnt].rgbBlue;
q += 3;
}
}
}
break;
case 4:
nUsed = (pbBmHdr->biWidth + 1) / 2;
nUnused = (((nUsed + 3) / 4) * 4) - nUsed;
nBytesWide = nUsed + nUnused;
nLastNibs = 2 - ((nUsed * 2) - pbBmHdr->biWidth);
for (r=0; r < pbBmHdr->biHeight;r++)
{
for (p=0,q=0; p < nUsed;p++)
{
nRow=(pbBmHdr->biHeight-r-1) * nBytesWide;
nByte = nRow + p;
int nNibbles = (p >> (4- (n * 4)) );
// ^^ Not sure about this symbol. Might be problem.
jsmpPixels[r][q+0] = pCTab[bytCTEnt].rgbRed;
jsmpPixels[r][q+1] = pCTab[bytCTEnt].rgbGreen;
jsmpPixels[r][q+2] = pCTab[bytCTEnt].rgbBlue;
q += 3;
}
}
break;
default:
case 8: //Each byte is a pointer to a pixel color
nUnused = (((pbBmHdr->biWidth + 3) / 4) * 4) -
pbBmHdr->biWidth;
for (r=0;r < pbBmHdr->biHeight; r++)
{
for (p=0,q=0; p < pbBmHdr->biWidth; p++,q+=3)
{
nRow = (pbBmHdr->biHeight-r-1) * (pbBmHdr->biWidth + nUnused);
nPixel = nRow + p;
jsmpPixels[r][q+0] = pCTab[lpPixels[nPixel]].rgbRed;
jsmpPixels[r][q+1] = pCTab[lpPixels[nPixel]].rgbGreen;
jsmpPixels[r][q+2] = pCTab[lpPixels[nPixel]].rgbBlue;
}
}
break;
case 16: //Hi-color (16 bits per pixel)
for (r=0;r < pbBmHdr->biHeight; r++)
{
for (p=0,q=0; p < pbBmHdr->biWidth; p++,q+=3)
{
nRow = (pbBmHdr->biHeight-r-1) * pbBmHdr->biWidth;
nPixel = nRow + p;
RGBQUAD quad = QuadFromWord(wPixels[nPixel]);
jsmpPixels[r][q+0] = quad.rgbRed;
jsmpPixels[r][q+1] = quad.rgbGreen;
jsmpPixels[r][q+2] = quad.rgbBlue;
}
}
break;
case 24:
nBytesWide = (pbBmHdr->biWidth*3);
nUnused = (((nBytesWide + 3) / 4) * 4) -
nBytesWide;
nBytesWide += nUnused;
for (r=0; r < pbBmHdr->biHeight; r++)
{
for (p=0,q=0;p < (nBytesWide-nUnused); p+=3,q+=3)
{
nRow = (pbBmHdr->biHeight-r-1) * nBytesWide;
nPixel = nRow + p;
jsmpPixels[r][q+0] = lpPixels[nPixel+2]; //Red
jsmpPixels[r][q+1] = lpPixels[nPixel+1]; //Green
jsmpPixels[r][q+2] = lpPixels[nPixel+0]; //Blue
}
}
break;
case 32:
for (r=0; r < pbBmHdr->biHeight; r++)
{
for (p=0,q=0; p < pbBmHdr->biWidth; p++,q+=3)
{
nRow = (pbBmHdr->biHeight-r-1) *
pbBmHdr->biWidth;
nPixel = nRow + p;
jsmpPixels[r][q+0] = pRgbQs[nPixel].rgbRed;
jsmpPixels[r][q+1] = pRgbQs[nPixel].rgbGreen;
jsmpPixels[r][q+2] = pRgbQs[nPixel].rgbBlue;
}
}
break;
} //end switch
return TRUE;
}
////////////////////////////////////////
//This function turns a 16-bit pixel
//into an RGBQUAD value.
////////////////////////////////////////
RGBQUAD CBitmapFile::QuadFromWord(WORD b16)
{
BYTE bytVals[] =
{
0, 16, 24, 32, 40, 48, 56, 64,
72, 80, 88, 96, 104,112,120,128,
136,144,152,160,168,176,184,192,
200,208,216,224,232,240,248,255
};
WORD wR = b16;
WORD wG = b16;
WORD wB = b16;
wR <<= 1; wR >>= 11;
wG <<= 6; wG >>= 11;
wB <<= 11; wB >>= 11;
RGBQUAD rgb;
rgb.rgbReserved = 0;
rgb.rgbBlue = bytVals[wB];
rgb.rgbGreen = bytVals[wG];
rgb.rgbRed = bytVals[wR];
return rgb;
}
//////////////////////////////////////////////////////////////////////////////////////////////////