ComImage
来源:互联网 发布:远程桌面登陆软件 编辑:程序博客网 时间:2024/04/30 09:39
//#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;
}
*/