//
#include "StdAfx.h"
#include < Windows.h >
#include < stdlib.h >
#include < stdio.h >
#include " ComImage.h "
#include " ComFun.h "
HANDLE DDBToDIB(HBITMAP hBitmap, HPALETTE hPalette, BITMAPINFO * pOutDibInfo, int nBitpPix)
{
BITMAP BM;
BITMAPINFOHEADER BMinfoh;
BITMAPINFO * pBMinfo;
HPALETTE hPalOld = NULL;
DWORD dwLenDib, dwBmInfoLen;
HANDLE hDIB;
HDC hDC;
int nColors;
BOOL bRetVal;
if (hBitmap == NULL)
{
::SetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
if (hPalette == NULL)
hPalette = (HPALETTE)::GetStockObject(DEFAULT_PALETTE);
GetObject(hBitmap, sizeof (BITMAP), (LPVOID) & BM);
BMinfoh.biSize = sizeof (BITMAPINFOHEADER);
BMinfoh.biWidth = BM.bmWidth;
BMinfoh.biHeight = BM.bmHeight;
BMinfoh.biPlanes = 1 ; // Must 1
if (nBitpPix == 0 )
BMinfoh.biBitCount = BM.bmPlanes * BM.bmBitsPixel;
else
BMinfoh.biBitCount = BM.bmPlanes * nBitpPix;
BMinfoh.biCompression = BI_RGB;
BMinfoh.biSizeImage = 0 ;
BMinfoh.biXPelsPerMeter = 0 ;
BMinfoh.biYPelsPerMeter = 0 ;
BMinfoh.biClrUsed = 0 ;
BMinfoh.biClrImportant = 0 ;
if (BMinfoh.biBitCount > 8 ) nColors = 0 ;
else nColors = 1 << BMinfoh.biBitCount;
dwBmInfoLen = BMinfoh.biSize + nColors * sizeof (RGBQUAD);
hDC = GetDC(NULL);
if (hPalette)
{
hPalOld = SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
}
pBMinfo = (BITMAPINFO * )GlobalAlloc(GMEM_FIXED, dwBmInfoLen);
if (pBMinfo == NULL)
{
SelectPalette(hDC, hPalOld, FALSE);
ReleaseDC(NULL, hDC);
::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
memcpy( & pBMinfo -> bmiHeader, & BMinfoh, sizeof (BITMAPINFOHEADER));
GetDIBits(hDC, hBitmap, 0 , BMinfoh.biHeight, NULL, pBMinfo, DIB_RGB_COLORS);
if (pBMinfo -> bmiHeader.biSizeImage == 0 )
{
pBMinfo -> bmiHeader.biSizeImage = ((((pBMinfo -> bmiHeader.biWidth * pBMinfo -> bmiHeader.biBitCount) + 31 ) & ~ 31 ) / 8 )
* pBMinfo -> bmiHeader.biHeight;
}
dwLenDib = dwBmInfoLen + pBMinfo -> bmiHeader.biSizeImage;
hDIB = GlobalAlloc(GMEM_FIXED, dwLenDib);
if (hDIB == NULL)
{
GlobalFree(pBMinfo);
if (hPalOld) SelectPalette(hDC, hPalOld, FALSE);
ReleaseDC(NULL, hDC);
return NULL;
}
memcpy(hDIB, pBMinfo, sizeof (BITMAPINFOHEADER));
bRetVal = GetDIBits(hDC, hBitmap, 0 , BMinfoh.biHeight,
(LPBYTE)hDIB + (BMinfoh.biSize + nColors * sizeof (RGBQUAD)),
pBMinfo, DIB_RGB_COLORS);
if ( bRetVal == FALSE )
{
GlobalFree(hDIB);
GlobalFree(pBMinfo);
if (hPalOld) SelectPalette(hDC, hPalOld, FALSE);
ReleaseDC(NULL, hDC);
return NULL;
}
if (pOutDibInfo != NULL)
memcpy(pOutDibInfo, pBMinfo, dwBmInfoLen);
GlobalFree(pBMinfo);
if (hPalOld) SelectPalette(hDC, hPalOld, FALSE);
ReleaseDC(NULL, hDC);
return hDIB;
}
BOOL SaveDIBToBMP(HANDLE hDib, CHAR * pFileName)
{
BITMAPFILEHEADER BmFileHead;
BITMAPINFOHEADER * pBmInfoHead;
int nColors;
HANDLE hFile;
DWORD dwWrite;
DWORD dwDibSize;
if ( ! hDib)
{
::SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
hFile = CreateFileA(pFileName, GENERIC_WRITE, 0 , NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}
pBmInfoHead = (BITMAPINFOHEADER * )hDib;
if (pBmInfoHead -> biBitCount > 8 ) nColors = 0 ;
else nColors = 1 << pBmInfoHead -> biBitCount;
dwDibSize = pBmInfoHead -> biSize + nColors * sizeof (RGBQUAD) + pBmInfoHead -> biSizeImage;
BmFileHead.bfType = ((WORD) ( ' M ' << 8 ) | ' B ' ); // "BM"
BmFileHead.bfSize = dwDibSize + sizeof (BITMAPFILEHEADER);
BmFileHead.bfReserved1 = 0 ;
BmFileHead.bfReserved2 = 0 ;
BmFileHead.bfOffBits = (DWORD) ( sizeof ( BITMAPFILEHEADER ) + pBmInfoHead -> biSize + nColors * sizeof (RGBQUAD));
WriteFile(hFile, & BmFileHead, sizeof (BITMAPFILEHEADER), & dwWrite, NULL);
WriteFile(hFile, hDib, dwDibSize, & dwWrite, NULL);
CloseHandle(hFile);
return TRUE;
}
BOOL SaveBitmapToFile(HBITMAP hBitmap, CHAR * pFileName)
{
HANDLE hDib = NULL;
HPALETTE hPalette = NULL;
BOOL bRetVal;
hDib = DDBToDIB(hBitmap, hPalette);
if (hDib == NULL)
{
return FALSE;
}
bRetVal = SaveDIBToBMP(hDib, pFileName);
GlobalFree(hDib);
return bRetVal;
}
HANDLE GetDIBFromWindow(HWND hWnd, RECT * pWndRect)
{
HANDLE hDib;
HBITMAP hBitmap, hOldBitmap;
HDC hWndDc, hMemDc;
RECT WndRect;
int nWidth, nHeigh;
hWndDc = ::GetWindowDC(hWnd);
hMemDc = ::CreateCompatibleDC(hWndDc);
if (pWndRect == NULL)
{
if (hWnd == HWND_DESKTOP)
{
nWidth = GetSystemMetrics(SM_CXSCREEN);
nHeigh = GetSystemMetrics(SM_CYSCREEN);
}
else
{
::GetWindowRect(hWnd, & WndRect);
nWidth = WndRect.right - WndRect.left;
nHeigh = WndRect.bottom - WndRect.top;
}
}
else
{
nWidth = pWndRect -> right - pWndRect -> left;
nHeigh = pWndRect -> bottom - pWndRect -> top;
}
hBitmap = ::CreateCompatibleBitmap(hWndDc, nWidth, nHeigh);
hOldBitmap = (HBITMAP)::SelectObject(hMemDc, hBitmap);
BitBlt(hMemDc, 0 , 0 , nWidth, nHeigh, hWndDc, 0 , 0 , SRCCOPY);
hDib = DDBToDIB(hBitmap);
::SelectObject(hMemDc, hOldBitmap);
::DeleteObject(hBitmap);
::DeleteDC(hMemDc);
::ReleaseDC(hWnd, hWndDc);
return hDib;
}
BOOL SaveWindowToBMP(CHAR * pBMPName, HWND hWnd, RECT * pWndRect)
{
HANDLE hDib;
::ShowWindow(hWnd, SW_SHOW);
::BringWindowToTop(hWnd);
::UpdateWindow(hWnd);
hDib = GetDIBFromWindow(hWnd, pWndRect);
SaveDIBToBMP(hDib, pBMPName);
GlobalFree(hDib);
return TRUE;
}
BOOL GetBitmapSize(HBITMAP hBitmap, DWORD * pdwBmInfoSize, DWORD * pdwDIBSize, int nBit)
{
BITMAP BM;
int nRetVal, nColors, nBitpPix;
if (hBitmap == NULL)
{
::SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
nRetVal = GetObject(hBitmap, sizeof (BITMAP), (LPVOID) & BM);
if (nRetVal != sizeof (BITMAP))
{
Msgerr( " GetObject " );
return FALSE;
}
if (nBit != 0 ) nBitpPix = nBit;
else nBitpPix = BM.bmBitsPixel;
nColors = 1 << nBitpPix;
if (nBitpPix <= 8 )
* pdwBmInfoSize = sizeof (BITMAPINFOHEADER) + nColors * sizeof (RGBQUAD);
else // 无调色板
* pdwBmInfoSize = sizeof (BITMAPINFOHEADER);
* pdwDIBSize = * pdwBmInfoSize + ((BM.bmWidth * nBitpPix + 31 ) / 32 ) * 4 * BM.bmHeight;
return TRUE;
}
BOOL SaveHiconToICOFile(HICON hIcon, CHAR * pFileName, int nBit)
{
ICONHEADER IconHead;
ICONDIRENTRY IconDir;
ICONINFO IconInfo;
HANDLE hFile;
VOID * pColorDIB;
VOID * pMaskDIB;
BITMAPINFO * pColorInfo;
BITMAPINFO * phMaskInfo;
DWORD dwColorInfoSize, dwMaskInfoSize;
DWORD dwColorDIBSize, dwMaskDIBSize;
DWORD dwWrite;
BOOL bRetVal;
if (hIcon == NULL || pFileName == NULL)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (nBit != 0 && nBit != 1 && nBit != 4 && nBit != 5 &&
nBit != 16 && nBit != 32 )
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
hFile = CreateFileA(pFileName, GENERIC_WRITE, 0 , NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}
memset( & IconHead, 0 , sizeof (IconHead));
memset( & IconDir, 0 , sizeof (IconDir));
GetIconInfo(hIcon, & IconInfo);
GetBitmapSize(IconInfo.hbmColor, & dwColorInfoSize, & dwColorDIBSize, nBit);
GetBitmapSize(IconInfo.hbmColor, & dwMaskInfoSize, & dwMaskDIBSize, 1 );
pColorInfo = (BITMAPINFO * )malloc(dwColorInfoSize);
phMaskInfo = (BITMAPINFO * )malloc(dwMaskInfoSize);
if (pColorInfo == NULL || phMaskInfo == NULL)
{
::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
memset(pColorInfo, 0 , dwColorInfoSize);
memset(phMaskInfo, 0 , dwMaskInfoSize);
pColorDIB = DDBToDIB(IconInfo.hbmColor, NULL, pColorInfo, 0 );
pMaskDIB = DDBToDIB(IconInfo.hbmMask, NULL, phMaskInfo, 1 ); // 单色蒙板
IconHead.idReserved = 0 ;
IconHead.idType = 1 ;
IconHead.idCount = 1 ; // 一个图标
IconDir.bWidth = (BYTE)pColorInfo -> bmiHeader.biWidth;
IconDir.bHeight = (BYTE)pColorInfo -> bmiHeader.biHeight;
IconDir.bColorCount = pColorInfo -> bmiHeader.biPlanes * pColorInfo -> bmiHeader.biBitCount;
IconDir.dwBytesInRes = dwColorDIBSize + dwMaskDIBSize - dwMaskInfoSize;
IconDir.dwImageOffset = sizeof (IconHead) + sizeof (IconDir);
bRetVal &= WriteFile(hFile, & IconHead, sizeof (IconHead), & dwWrite, NULL);
bRetVal &= WriteFile(hFile, & IconDir, sizeof (IconDir), & dwWrite, NULL);
pColorInfo -> bmiHeader.biHeight *= 2 ; // Color + Mask
pColorInfo -> bmiHeader.biSizeImage += dwMaskDIBSize - dwMaskInfoSize;
bRetVal &= WriteFile(hFile, pColorInfo, dwColorInfoSize, & dwWrite, NULL);
bRetVal &= WriteFile(hFile, (BYTE * )pColorDIB + dwColorInfoSize, dwColorDIBSize - dwColorInfoSize, & dwWrite, NULL);
bRetVal &= WriteFile(hFile, (BYTE * )pMaskDIB + dwMaskInfoSize, dwMaskDIBSize - dwMaskInfoSize, & dwWrite, NULL);
// Ben: WriteFile() do the correct thing, but return 0, so:
DWORD nErr;
nErr = GetLastError();
bRetVal = ( 0 == nErr) ? TRUE:FALSE;
free(pColorInfo);
free(phMaskInfo);
GlobalFree(pColorDIB); // for DDBToDIB
GlobalFree(pMaskDIB);
DeleteObject(IconInfo.hbmColor);
DeleteObject(IconInfo.hbmMask);
CloseHandle(hFile);
return bRetVal;
}
DWORD DibMaskFill(HANDLE hDib, HANDLE hMaskDib, COLORREF Color)
{
BITMAPINFO * pColorInfo;
BITMAPINFO * phMaskInfo;
pColorInfo = (BITMAPINFO * )hDib;
phMaskInfo = (BITMAPINFO * )hMaskDib;
if (phMaskInfo -> bmiHeader.biBitCount > 2 ) // 蒙板 不是单色
{
return 0 ;
}
return 0 ;
}
HBITMAP GetHiconBitmap(HICON hIcon, COLORREF Color)
{
ICONINFO IconInfo;
BITMAP BM;
HBITMAP hBitmap, hBitmapOld1, hBitmapOld2;
BOOL bRetVal = TRUE;
HDC hmDC, hMemDc1, hMemDc2;
hmDC = GetDC(NULL);
hMemDc1 = CreateCompatibleDC(hmDC);
hMemDc2 = CreateCompatibleDC(hmDC);
if (GetIconInfo(hIcon, & IconInfo) == FALSE)
{
Msgerr( " GetIconInfo Error! " );
return NULL;
}
GetObject(IconInfo.hbmColor, sizeof (BITMAP), & BM);
hBitmap = CreateBitmap(BM.bmWidth, BM.bmHeight, BM.bmPlanes, BM.bmBitsPixel, NULL);
hBitmapOld1 = (HBITMAP)::SelectObject(hMemDc1, hBitmap);
hBitmapOld2 = (HBITMAP)::SelectObject(hMemDc2, IconInfo.hbmColor);
FloodFill(hMemDc1, 0 , 0 , Color);
bRetVal = MaskBlt(hMemDc1, 0 , 0 , BM.bmWidth, BM.bmHeight, hMemDc2, 0 , 0 , IconInfo.hbmMask, 0 , 0 , 0xCCAA0000 );
if (bRetVal == FALSE)
{
Msgerr( " MaskBlt Error " );
return NULL;
}
::SelectObject(hMemDc1, hBitmapOld1);
::SelectObject(hMemDc2, hBitmapOld2);
DeleteObject(IconInfo.hbmColor);
DeleteObject(IconInfo.hbmMask);
DeleteDC(hMemDc1);
DeleteDC(hMemDc2);
::ReleaseDC(NULL, hmDC);
return hBitmap;
}
#ifdef USEJPEGLIB
BOOL SaveBitmapToJPG(HBITMAP hBitMap, CHAR * pJPGName, int nQuality)
{
HANDLE hDib = NULL;
HPALETTE hPalette = NULL;
BOOL bRetVal;
hDib = DDBToDIB(hBitMap, hPalette);
if (hDib == NULL)
{
return FALSE;
}
bRetVal = JpegFromDib(hDib, nQuality, pJPGName);
GlobalFree(hDib);
return bRetVal;
}
RGBQUAD 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;
RGBQUAD rgb;
wR <<= 1 ; wR >>= 11 ;
wG <<= 6 ; wG >>= 11 ;
wB <<= 11 ; wB >>= 11 ;
rgb.rgbReserved = 0 ;
rgb.rgbBlue = bytVals[wB];
rgb.rgbGreen = bytVals[wG];
rgb.rgbRed = bytVals[wR];
return rgb;
}
BOOL DibToSamps(HANDLE hDib, int nSampsPerRow, struct jpeg_compress_struct cinfo,
JSAMPARRAY jsmpPixels)
{
// Sanity...
if (hDib == NULL || nSampsPerRow <= 0 )
{
::SetLastError(ERROR_INVALID_HANDLE);
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 :
::SetLastError(ERROR_INVALID_HANDLE);
return FALSE; // Unsupported format
}
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 )) );
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;
}
BOOL JpegFromDib(HANDLE hDib, int nQuality, CHAR * pJPGName)
{
BOOL bRetVal;
int nError;
// Basic sanity checks...
if (nQuality < 0 || nQuality > 100 || hDib == NULL)
{
::SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
byte * buf2 = 0 ;
// Use libjpeg functions to write scanlines to disk in JPEG format
jpeg_compress_struct * pcinfo = (jpeg_compress_struct * )malloc( sizeof (jpeg_compress_struct) * 4 );
memset(pcinfo, 0 , sizeof (jpeg_compress_struct) * 4 ); // WARNING jpeg_start_compress OVER
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
pcinfo -> err = jpeg_std_error( & jerr); // Use default error handling (ugly!)
jpeg_create_compress(pcinfo);
pOutFile = fopen(pJPGName, " wb " );
if (pOutFile == NULL)
{
nError = ::GetLastError();
jpeg_destroy_compress(pcinfo);
::SetLastError(nError);
free(pcinfo);
return FALSE;
}
jpeg_stdio_dest(pcinfo, pOutFile);
LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)hDib;
pcinfo -> image_width = lpbi -> biWidth; // Image width and height, in pixels
pcinfo -> image_height = lpbi -> biHeight;
pcinfo -> input_components = 3 ; // Color components per pixel
// (RGB_PIXELSIZE - see jmorecfg.h)
pcinfo -> in_color_space = JCS_RGB; // Colorspace of input image
jpeg_set_defaults(pcinfo);
jpeg_set_quality(pcinfo, nQuality, TRUE); // Limit to baseline-JPEG values
jpeg_start_compress(pcinfo, TRUE);
// JSAMPLEs per row in output buffer
nSampsPerRow = pcinfo -> image_width * pcinfo -> input_components;
// Allocate array of pixel RGB values
jsmpArray = ( * pcinfo -> mem -> alloc_sarray)
((j_common_ptr) pcinfo, JPOOL_IMAGE, nSampsPerRow, pcinfo -> image_height);
bRetVal = DibToSamps(hDib, nSampsPerRow, * pcinfo, jsmpArray);
if (bRetVal == FALSE)
{
nError = ::GetLastError();
jpeg_finish_compress(pcinfo); // Always finish
fclose(pOutFile);
jpeg_destroy_compress(pcinfo); // Free resources
free(pcinfo);
::SetLastError(nError);
return FALSE;
}
// Write the array of scan lines to the JPEG file
jpeg_write_scanlines(pcinfo, jsmpArray, pcinfo -> image_height);
jpeg_finish_compress(pcinfo); // Always finish
fclose(pOutFile);
jpeg_destroy_compress(pcinfo); // Free resources
free(pcinfo);
return TRUE;
}
#endif
/*
// Bmp转换为Ico格式, nBit为色彩位数, 支持位数如下:
// 0, 1, 4, 8, 16, 24, 32
//-------------------------
void Bmp2Ico(String strBmpFileName, int nBit)
{
int nIconWidth = GetSystemMetrics(SM_CXICON);
int nIconHeight = GetSystemMetrics(SM_CYICON);;
Graphics::TBitmap *MyBmp = new Graphics::TBitmap();
MyBmp->LoadFromFile(strBmpFileName);
Graphics::TBitmap *AndMask = new Graphics::TBitmap();
AndMask->Width = nIconWidth;
AndMask->Height = nIconHeight;
AndMask->Canvas->Brush->Color = clBlack;
AndMask->Canvas->Rectangle(0, 0, nIconWidth, nIconHeight);
Graphics::TBitmap *XorMask = new Graphics::TBitmap();
XorMask->Width = nIconWidth;
XorMask->Height = nIconHeight;
StretchBlt(XorMask->Canvas->Handle, 0, 0, nIconWidth, nIconHeight,
MyBmp->Canvas->Handle, 0, 0, MyBmp->Width, MyBmp->Height, SRCCOPY);
TIcon *pIcon = new TIcon();
TIconInfo IconInfo;
IconInfo.fIcon = true;
IconInfo.xHotspot = 0;
IconInfo.yHotspot = 0;
IconInfo.hbmMask = AndMask->Handle;
IconInfo.hbmColor = XorMask->Handle;
pIcon->Handle = CreateIconIndirect(&IconInfo);
delete AndMask;
delete XorMask;
delete MyBmp;
String strIcoFileName = ChangeFileExt(strBmpFileName, ".ico");
SaveIcon(pIcon->Handle, strIcoFileName.c_str(), nBit);
delete pIcon;
}
*/
#include < Windows.h >
#include < stdlib.h >
#include < stdio.h >
#include " ComImage.h "
#include " ComFun.h "
HANDLE DDBToDIB(HBITMAP hBitmap, HPALETTE hPalette, BITMAPINFO * pOutDibInfo, int nBitpPix)
{
BITMAP BM;
BITMAPINFOHEADER BMinfoh;
BITMAPINFO * pBMinfo;
HPALETTE hPalOld = NULL;
DWORD dwLenDib, dwBmInfoLen;
HANDLE hDIB;
HDC hDC;
int nColors;
BOOL bRetVal;
if (hBitmap == NULL)
{
::SetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
if (hPalette == NULL)
hPalette = (HPALETTE)::GetStockObject(DEFAULT_PALETTE);
GetObject(hBitmap, sizeof (BITMAP), (LPVOID) & BM);
BMinfoh.biSize = sizeof (BITMAPINFOHEADER);
BMinfoh.biWidth = BM.bmWidth;
BMinfoh.biHeight = BM.bmHeight;
BMinfoh.biPlanes = 1 ; // Must 1
if (nBitpPix == 0 )
BMinfoh.biBitCount = BM.bmPlanes * BM.bmBitsPixel;
else
BMinfoh.biBitCount = BM.bmPlanes * nBitpPix;
BMinfoh.biCompression = BI_RGB;
BMinfoh.biSizeImage = 0 ;
BMinfoh.biXPelsPerMeter = 0 ;
BMinfoh.biYPelsPerMeter = 0 ;
BMinfoh.biClrUsed = 0 ;
BMinfoh.biClrImportant = 0 ;
if (BMinfoh.biBitCount > 8 ) nColors = 0 ;
else nColors = 1 << BMinfoh.biBitCount;
dwBmInfoLen = BMinfoh.biSize + nColors * sizeof (RGBQUAD);
hDC = GetDC(NULL);
if (hPalette)
{
hPalOld = SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
}
pBMinfo = (BITMAPINFO * )GlobalAlloc(GMEM_FIXED, dwBmInfoLen);
if (pBMinfo == NULL)
{
SelectPalette(hDC, hPalOld, FALSE);
ReleaseDC(NULL, hDC);
::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
memcpy( & pBMinfo -> bmiHeader, & BMinfoh, sizeof (BITMAPINFOHEADER));
GetDIBits(hDC, hBitmap, 0 , BMinfoh.biHeight, NULL, pBMinfo, DIB_RGB_COLORS);
if (pBMinfo -> bmiHeader.biSizeImage == 0 )
{
pBMinfo -> bmiHeader.biSizeImage = ((((pBMinfo -> bmiHeader.biWidth * pBMinfo -> bmiHeader.biBitCount) + 31 ) & ~ 31 ) / 8 )
* pBMinfo -> bmiHeader.biHeight;
}
dwLenDib = dwBmInfoLen + pBMinfo -> bmiHeader.biSizeImage;
hDIB = GlobalAlloc(GMEM_FIXED, dwLenDib);
if (hDIB == NULL)
{
GlobalFree(pBMinfo);
if (hPalOld) SelectPalette(hDC, hPalOld, FALSE);
ReleaseDC(NULL, hDC);
return NULL;
}
memcpy(hDIB, pBMinfo, sizeof (BITMAPINFOHEADER));
bRetVal = GetDIBits(hDC, hBitmap, 0 , BMinfoh.biHeight,
(LPBYTE)hDIB + (BMinfoh.biSize + nColors * sizeof (RGBQUAD)),
pBMinfo, DIB_RGB_COLORS);
if ( bRetVal == FALSE )
{
GlobalFree(hDIB);
GlobalFree(pBMinfo);
if (hPalOld) SelectPalette(hDC, hPalOld, FALSE);
ReleaseDC(NULL, hDC);
return NULL;
}
if (pOutDibInfo != NULL)
memcpy(pOutDibInfo, pBMinfo, dwBmInfoLen);
GlobalFree(pBMinfo);
if (hPalOld) SelectPalette(hDC, hPalOld, FALSE);
ReleaseDC(NULL, hDC);
return hDIB;
}
BOOL SaveDIBToBMP(HANDLE hDib, CHAR * pFileName)
{
BITMAPFILEHEADER BmFileHead;
BITMAPINFOHEADER * pBmInfoHead;
int nColors;
HANDLE hFile;
DWORD dwWrite;
DWORD dwDibSize;
if ( ! hDib)
{
::SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
hFile = CreateFileA(pFileName, GENERIC_WRITE, 0 , NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}
pBmInfoHead = (BITMAPINFOHEADER * )hDib;
if (pBmInfoHead -> biBitCount > 8 ) nColors = 0 ;
else nColors = 1 << pBmInfoHead -> biBitCount;
dwDibSize = pBmInfoHead -> biSize + nColors * sizeof (RGBQUAD) + pBmInfoHead -> biSizeImage;
BmFileHead.bfType = ((WORD) ( ' M ' << 8 ) | ' B ' ); // "BM"
BmFileHead.bfSize = dwDibSize + sizeof (BITMAPFILEHEADER);
BmFileHead.bfReserved1 = 0 ;
BmFileHead.bfReserved2 = 0 ;
BmFileHead.bfOffBits = (DWORD) ( sizeof ( BITMAPFILEHEADER ) + pBmInfoHead -> biSize + nColors * sizeof (RGBQUAD));
WriteFile(hFile, & BmFileHead, sizeof (BITMAPFILEHEADER), & dwWrite, NULL);
WriteFile(hFile, hDib, dwDibSize, & dwWrite, NULL);
CloseHandle(hFile);
return TRUE;
}
BOOL SaveBitmapToFile(HBITMAP hBitmap, CHAR * pFileName)
{
HANDLE hDib = NULL;
HPALETTE hPalette = NULL;
BOOL bRetVal;
hDib = DDBToDIB(hBitmap, hPalette);
if (hDib == NULL)
{
return FALSE;
}
bRetVal = SaveDIBToBMP(hDib, pFileName);
GlobalFree(hDib);
return bRetVal;
}
HANDLE GetDIBFromWindow(HWND hWnd, RECT * pWndRect)
{
HANDLE hDib;
HBITMAP hBitmap, hOldBitmap;
HDC hWndDc, hMemDc;
RECT WndRect;
int nWidth, nHeigh;
hWndDc = ::GetWindowDC(hWnd);
hMemDc = ::CreateCompatibleDC(hWndDc);
if (pWndRect == NULL)
{
if (hWnd == HWND_DESKTOP)
{
nWidth = GetSystemMetrics(SM_CXSCREEN);
nHeigh = GetSystemMetrics(SM_CYSCREEN);
}
else
{
::GetWindowRect(hWnd, & WndRect);
nWidth = WndRect.right - WndRect.left;
nHeigh = WndRect.bottom - WndRect.top;
}
}
else
{
nWidth = pWndRect -> right - pWndRect -> left;
nHeigh = pWndRect -> bottom - pWndRect -> top;
}
hBitmap = ::CreateCompatibleBitmap(hWndDc, nWidth, nHeigh);
hOldBitmap = (HBITMAP)::SelectObject(hMemDc, hBitmap);
BitBlt(hMemDc, 0 , 0 , nWidth, nHeigh, hWndDc, 0 , 0 , SRCCOPY);
hDib = DDBToDIB(hBitmap);
::SelectObject(hMemDc, hOldBitmap);
::DeleteObject(hBitmap);
::DeleteDC(hMemDc);
::ReleaseDC(hWnd, hWndDc);
return hDib;
}
BOOL SaveWindowToBMP(CHAR * pBMPName, HWND hWnd, RECT * pWndRect)
{
HANDLE hDib;
::ShowWindow(hWnd, SW_SHOW);
::BringWindowToTop(hWnd);
::UpdateWindow(hWnd);
hDib = GetDIBFromWindow(hWnd, pWndRect);
SaveDIBToBMP(hDib, pBMPName);
GlobalFree(hDib);
return TRUE;
}
BOOL GetBitmapSize(HBITMAP hBitmap, DWORD * pdwBmInfoSize, DWORD * pdwDIBSize, int nBit)
{
BITMAP BM;
int nRetVal, nColors, nBitpPix;
if (hBitmap == NULL)
{
::SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
nRetVal = GetObject(hBitmap, sizeof (BITMAP), (LPVOID) & BM);
if (nRetVal != sizeof (BITMAP))
{
Msgerr( " GetObject " );
return FALSE;
}
if (nBit != 0 ) nBitpPix = nBit;
else nBitpPix = BM.bmBitsPixel;
nColors = 1 << nBitpPix;
if (nBitpPix <= 8 )
* pdwBmInfoSize = sizeof (BITMAPINFOHEADER) + nColors * sizeof (RGBQUAD);
else // 无调色板
* pdwBmInfoSize = sizeof (BITMAPINFOHEADER);
* pdwDIBSize = * pdwBmInfoSize + ((BM.bmWidth * nBitpPix + 31 ) / 32 ) * 4 * BM.bmHeight;
return TRUE;
}
BOOL SaveHiconToICOFile(HICON hIcon, CHAR * pFileName, int nBit)
{
ICONHEADER IconHead;
ICONDIRENTRY IconDir;
ICONINFO IconInfo;
HANDLE hFile;
VOID * pColorDIB;
VOID * pMaskDIB;
BITMAPINFO * pColorInfo;
BITMAPINFO * phMaskInfo;
DWORD dwColorInfoSize, dwMaskInfoSize;
DWORD dwColorDIBSize, dwMaskDIBSize;
DWORD dwWrite;
BOOL bRetVal;
if (hIcon == NULL || pFileName == NULL)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (nBit != 0 && nBit != 1 && nBit != 4 && nBit != 5 &&
nBit != 16 && nBit != 32 )
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
hFile = CreateFileA(pFileName, GENERIC_WRITE, 0 , NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}
memset( & IconHead, 0 , sizeof (IconHead));
memset( & IconDir, 0 , sizeof (IconDir));
GetIconInfo(hIcon, & IconInfo);
GetBitmapSize(IconInfo.hbmColor, & dwColorInfoSize, & dwColorDIBSize, nBit);
GetBitmapSize(IconInfo.hbmColor, & dwMaskInfoSize, & dwMaskDIBSize, 1 );
pColorInfo = (BITMAPINFO * )malloc(dwColorInfoSize);
phMaskInfo = (BITMAPINFO * )malloc(dwMaskInfoSize);
if (pColorInfo == NULL || phMaskInfo == NULL)
{
::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
memset(pColorInfo, 0 , dwColorInfoSize);
memset(phMaskInfo, 0 , dwMaskInfoSize);
pColorDIB = DDBToDIB(IconInfo.hbmColor, NULL, pColorInfo, 0 );
pMaskDIB = DDBToDIB(IconInfo.hbmMask, NULL, phMaskInfo, 1 ); // 单色蒙板
IconHead.idReserved = 0 ;
IconHead.idType = 1 ;
IconHead.idCount = 1 ; // 一个图标
IconDir.bWidth = (BYTE)pColorInfo -> bmiHeader.biWidth;
IconDir.bHeight = (BYTE)pColorInfo -> bmiHeader.biHeight;
IconDir.bColorCount = pColorInfo -> bmiHeader.biPlanes * pColorInfo -> bmiHeader.biBitCount;
IconDir.dwBytesInRes = dwColorDIBSize + dwMaskDIBSize - dwMaskInfoSize;
IconDir.dwImageOffset = sizeof (IconHead) + sizeof (IconDir);
bRetVal &= WriteFile(hFile, & IconHead, sizeof (IconHead), & dwWrite, NULL);
bRetVal &= WriteFile(hFile, & IconDir, sizeof (IconDir), & dwWrite, NULL);
pColorInfo -> bmiHeader.biHeight *= 2 ; // Color + Mask
pColorInfo -> bmiHeader.biSizeImage += dwMaskDIBSize - dwMaskInfoSize;
bRetVal &= WriteFile(hFile, pColorInfo, dwColorInfoSize, & dwWrite, NULL);
bRetVal &= WriteFile(hFile, (BYTE * )pColorDIB + dwColorInfoSize, dwColorDIBSize - dwColorInfoSize, & dwWrite, NULL);
bRetVal &= WriteFile(hFile, (BYTE * )pMaskDIB + dwMaskInfoSize, dwMaskDIBSize - dwMaskInfoSize, & dwWrite, NULL);
// Ben: WriteFile() do the correct thing, but return 0, so:
DWORD nErr;
nErr = GetLastError();
bRetVal = ( 0 == nErr) ? TRUE:FALSE;
free(pColorInfo);
free(phMaskInfo);
GlobalFree(pColorDIB); // for DDBToDIB
GlobalFree(pMaskDIB);
DeleteObject(IconInfo.hbmColor);
DeleteObject(IconInfo.hbmMask);
CloseHandle(hFile);
return bRetVal;
}
DWORD DibMaskFill(HANDLE hDib, HANDLE hMaskDib, COLORREF Color)
{
BITMAPINFO * pColorInfo;
BITMAPINFO * phMaskInfo;
pColorInfo = (BITMAPINFO * )hDib;
phMaskInfo = (BITMAPINFO * )hMaskDib;
if (phMaskInfo -> bmiHeader.biBitCount > 2 ) // 蒙板 不是单色
{
return 0 ;
}
return 0 ;
}
HBITMAP GetHiconBitmap(HICON hIcon, COLORREF Color)
{
ICONINFO IconInfo;
BITMAP BM;
HBITMAP hBitmap, hBitmapOld1, hBitmapOld2;
BOOL bRetVal = TRUE;
HDC hmDC, hMemDc1, hMemDc2;
hmDC = GetDC(NULL);
hMemDc1 = CreateCompatibleDC(hmDC);
hMemDc2 = CreateCompatibleDC(hmDC);
if (GetIconInfo(hIcon, & IconInfo) == FALSE)
{
Msgerr( " GetIconInfo Error! " );
return NULL;
}
GetObject(IconInfo.hbmColor, sizeof (BITMAP), & BM);
hBitmap = CreateBitmap(BM.bmWidth, BM.bmHeight, BM.bmPlanes, BM.bmBitsPixel, NULL);
hBitmapOld1 = (HBITMAP)::SelectObject(hMemDc1, hBitmap);
hBitmapOld2 = (HBITMAP)::SelectObject(hMemDc2, IconInfo.hbmColor);
FloodFill(hMemDc1, 0 , 0 , Color);
bRetVal = MaskBlt(hMemDc1, 0 , 0 , BM.bmWidth, BM.bmHeight, hMemDc2, 0 , 0 , IconInfo.hbmMask, 0 , 0 , 0xCCAA0000 );
if (bRetVal == FALSE)
{
Msgerr( " MaskBlt Error " );
return NULL;
}
::SelectObject(hMemDc1, hBitmapOld1);
::SelectObject(hMemDc2, hBitmapOld2);
DeleteObject(IconInfo.hbmColor);
DeleteObject(IconInfo.hbmMask);
DeleteDC(hMemDc1);
DeleteDC(hMemDc2);
::ReleaseDC(NULL, hmDC);
return hBitmap;
}
#ifdef USEJPEGLIB
BOOL SaveBitmapToJPG(HBITMAP hBitMap, CHAR * pJPGName, int nQuality)
{
HANDLE hDib = NULL;
HPALETTE hPalette = NULL;
BOOL bRetVal;
hDib = DDBToDIB(hBitMap, hPalette);
if (hDib == NULL)
{
return FALSE;
}
bRetVal = JpegFromDib(hDib, nQuality, pJPGName);
GlobalFree(hDib);
return bRetVal;
}
RGBQUAD 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;
RGBQUAD rgb;
wR <<= 1 ; wR >>= 11 ;
wG <<= 6 ; wG >>= 11 ;
wB <<= 11 ; wB >>= 11 ;
rgb.rgbReserved = 0 ;
rgb.rgbBlue = bytVals[wB];
rgb.rgbGreen = bytVals[wG];
rgb.rgbRed = bytVals[wR];
return rgb;
}
BOOL DibToSamps(HANDLE hDib, int nSampsPerRow, struct jpeg_compress_struct cinfo,
JSAMPARRAY jsmpPixels)
{
// Sanity...
if (hDib == NULL || nSampsPerRow <= 0 )
{
::SetLastError(ERROR_INVALID_HANDLE);
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 :
::SetLastError(ERROR_INVALID_HANDLE);
return FALSE; // Unsupported format
}
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 )) );
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;
}
BOOL JpegFromDib(HANDLE hDib, int nQuality, CHAR * pJPGName)
{
BOOL bRetVal;
int nError;
// Basic sanity checks...
if (nQuality < 0 || nQuality > 100 || hDib == NULL)
{
::SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
byte * buf2 = 0 ;
// Use libjpeg functions to write scanlines to disk in JPEG format
jpeg_compress_struct * pcinfo = (jpeg_compress_struct * )malloc( sizeof (jpeg_compress_struct) * 4 );
memset(pcinfo, 0 , sizeof (jpeg_compress_struct) * 4 ); // WARNING jpeg_start_compress OVER
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
pcinfo -> err = jpeg_std_error( & jerr); // Use default error handling (ugly!)
jpeg_create_compress(pcinfo);
pOutFile = fopen(pJPGName, " wb " );
if (pOutFile == NULL)
{
nError = ::GetLastError();
jpeg_destroy_compress(pcinfo);
::SetLastError(nError);
free(pcinfo);
return FALSE;
}
jpeg_stdio_dest(pcinfo, pOutFile);
LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)hDib;
pcinfo -> image_width = lpbi -> biWidth; // Image width and height, in pixels
pcinfo -> image_height = lpbi -> biHeight;
pcinfo -> input_components = 3 ; // Color components per pixel
// (RGB_PIXELSIZE - see jmorecfg.h)
pcinfo -> in_color_space = JCS_RGB; // Colorspace of input image
jpeg_set_defaults(pcinfo);
jpeg_set_quality(pcinfo, nQuality, TRUE); // Limit to baseline-JPEG values
jpeg_start_compress(pcinfo, TRUE);
// JSAMPLEs per row in output buffer
nSampsPerRow = pcinfo -> image_width * pcinfo -> input_components;
// Allocate array of pixel RGB values
jsmpArray = ( * pcinfo -> mem -> alloc_sarray)
((j_common_ptr) pcinfo, JPOOL_IMAGE, nSampsPerRow, pcinfo -> image_height);
bRetVal = DibToSamps(hDib, nSampsPerRow, * pcinfo, jsmpArray);
if (bRetVal == FALSE)
{
nError = ::GetLastError();
jpeg_finish_compress(pcinfo); // Always finish
fclose(pOutFile);
jpeg_destroy_compress(pcinfo); // Free resources
free(pcinfo);
::SetLastError(nError);
return FALSE;
}
// Write the array of scan lines to the JPEG file
jpeg_write_scanlines(pcinfo, jsmpArray, pcinfo -> image_height);
jpeg_finish_compress(pcinfo); // Always finish
fclose(pOutFile);
jpeg_destroy_compress(pcinfo); // Free resources
free(pcinfo);
return TRUE;
}
#endif
/*
// Bmp转换为Ico格式, nBit为色彩位数, 支持位数如下:
// 0, 1, 4, 8, 16, 24, 32
//-------------------------
void Bmp2Ico(String strBmpFileName, int nBit)
{
int nIconWidth = GetSystemMetrics(SM_CXICON);
int nIconHeight = GetSystemMetrics(SM_CYICON);;
Graphics::TBitmap *MyBmp = new Graphics::TBitmap();
MyBmp->LoadFromFile(strBmpFileName);
Graphics::TBitmap *AndMask = new Graphics::TBitmap();
AndMask->Width = nIconWidth;
AndMask->Height = nIconHeight;
AndMask->Canvas->Brush->Color = clBlack;
AndMask->Canvas->Rectangle(0, 0, nIconWidth, nIconHeight);
Graphics::TBitmap *XorMask = new Graphics::TBitmap();
XorMask->Width = nIconWidth;
XorMask->Height = nIconHeight;
StretchBlt(XorMask->Canvas->Handle, 0, 0, nIconWidth, nIconHeight,
MyBmp->Canvas->Handle, 0, 0, MyBmp->Width, MyBmp->Height, SRCCOPY);
TIcon *pIcon = new TIcon();
TIconInfo IconInfo;
IconInfo.fIcon = true;
IconInfo.xHotspot = 0;
IconInfo.yHotspot = 0;
IconInfo.hbmMask = AndMask->Handle;
IconInfo.hbmColor = XorMask->Handle;
pIcon->Handle = CreateIconIndirect(&IconInfo);
delete AndMask;
delete XorMask;
delete MyBmp;
String strIcoFileName = ChangeFileExt(strBmpFileName, ".ico");
SaveIcon(pIcon->Handle, strIcoFileName.c_str(), nBit);
delete pIcon;
}
*/