465 lines
12 KiB
C++
465 lines
12 KiB
C++
|
/*******************************************************************************
|
||
|
*
|
||
|
* (C) COPYRIGHT MICROSOFT CORP., 1997
|
||
|
*
|
||
|
* TITLE: Util.Cpp
|
||
|
*
|
||
|
* VERSION: 2.0
|
||
|
*
|
||
|
* AUTHOR: ReedB
|
||
|
*
|
||
|
* DATE: 26 Dec, 1997
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Implementation of common utility functions.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#include <objbase.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <tchar.h>
|
||
|
|
||
|
#include "wia.h"
|
||
|
#include "util.h"
|
||
|
#include "wiadebug.h"
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* G O L B A L D A T A
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
|
||
|
// extern HWND g_hWndListBox; // Optional debug listbox window handle.
|
||
|
// extern HANDLE g_hfDebugLog; // Optional debug log file handle.
|
||
|
// extern TCHAR g_szAppName[]; // Window caption.
|
||
|
|
||
|
|
||
|
namespace Util
|
||
|
{
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* SetBMI
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Setup bitmap info.
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
void _stdcall SetBMI(
|
||
|
PBITMAPINFO pbmi,
|
||
|
LONG width,
|
||
|
LONG height,
|
||
|
LONG depth)
|
||
|
{
|
||
|
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||
|
pbmi->bmiHeader.biWidth = width;
|
||
|
pbmi->bmiHeader.biHeight = height;
|
||
|
pbmi->bmiHeader.biPlanes = 1;
|
||
|
pbmi->bmiHeader.biBitCount = (WORD) depth;
|
||
|
pbmi->bmiHeader.biCompression = BI_RGB;
|
||
|
pbmi->bmiHeader.biSizeImage = 0;
|
||
|
pbmi->bmiHeader.biXPelsPerMeter = 0;
|
||
|
pbmi->bmiHeader.biYPelsPerMeter = 0;
|
||
|
pbmi->bmiHeader.biClrUsed = 0;
|
||
|
pbmi->bmiHeader.biClrImportant = 0;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* AllocDibFileFromBits
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Given an unaligned bits buffer, allocate a buffer lager enough to hold the
|
||
|
* DWORD aligned DIB file and fill it in.
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
PBYTE _stdcall AllocDibFileFromBits(
|
||
|
PBYTE pBits,
|
||
|
UINT width,
|
||
|
UINT height,
|
||
|
UINT depth)
|
||
|
{
|
||
|
PBYTE pdib;
|
||
|
UINT i, uiScanLineWidth, uiSrcScanLineWidth, cbDibSize;
|
||
|
|
||
|
// Align scanline to ULONG boundary
|
||
|
uiSrcScanLineWidth = (width * depth) / 8;
|
||
|
uiScanLineWidth = (uiSrcScanLineWidth + 3) & 0xfffffffc;
|
||
|
|
||
|
// Calculate DIB size and allocate memory for the DIB.
|
||
|
cbDibSize = height * uiScanLineWidth;
|
||
|
cbDibSize += sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO);
|
||
|
pdib = (PBYTE) LocalAlloc(0, cbDibSize);
|
||
|
if (pdib) {
|
||
|
PBITMAPFILEHEADER pbmfh = (PBITMAPFILEHEADER)pdib;
|
||
|
PBITMAPINFO pbmi = (PBITMAPINFO)(pdib + sizeof(BITMAPFILEHEADER));
|
||
|
PBYTE pb = (PBYTE)pbmi+ sizeof(BITMAPINFO);
|
||
|
|
||
|
// Setup bitmap file header.
|
||
|
pbmfh->bfType = 'MB';
|
||
|
pbmfh->bfSize = cbDibSize;
|
||
|
pbmfh->bfOffBits = static_cast<DWORD>(pb - pdib);
|
||
|
|
||
|
// Setup bitmap info.
|
||
|
SetBMI(pbmi,width, height, depth);
|
||
|
|
||
|
WIA_TRACE(("AllocDibFileFromBits, uiScanLineWidth: %d, pdib: 0x%08X, pbmi: 0x%08X, pbits: 0x%08X", uiScanLineWidth, pdib, pbmi, pb));
|
||
|
|
||
|
// Copy the bits.
|
||
|
for (i = 0; i < height; i++) {
|
||
|
memcpy(pb, pBits, uiSrcScanLineWidth);
|
||
|
pb += uiScanLineWidth;
|
||
|
pBits += uiScanLineWidth;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
WIA_ERROR(("AllocDibFileFromBits, LocalAlloc of %d bytes failed", cbDibSize));
|
||
|
}
|
||
|
return pdib;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* DIBBufferToBMP
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Make a BMP object from a DWORD aligned DIB file memory buffer
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
HBITMAP _stdcall DIBBufferToBMP(HDC hDC, PBYTE pDib, BOOLEAN bFlip)
|
||
|
{
|
||
|
HBITMAP hBmp = NULL;
|
||
|
PBITMAPINFO pbmi = (BITMAPINFO*)(pDib);
|
||
|
PBYTE pBits = pDib + GetBmiSize(pbmi);
|
||
|
|
||
|
if (bFlip) {
|
||
|
pbmi->bmiHeader.biHeight = -pbmi->bmiHeader.biHeight;
|
||
|
}
|
||
|
hBmp = CreateDIBitmap(hDC, &pbmi->bmiHeader, CBM_INIT, pBits, pbmi, DIB_RGB_COLORS);
|
||
|
if (!hBmp) {
|
||
|
WIA_ERROR(("DIBBufferToBMP, CreateDIBitmap failed %d", GetLastError()));
|
||
|
}
|
||
|
return hBmp;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* ReadDIBFile
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
HRESULT _stdcall ReadDIBFile(LPTSTR pszFileName, PBYTE *ppDib)
|
||
|
{
|
||
|
HRESULT hr = S_FALSE;
|
||
|
HANDLE hFile, hMap;
|
||
|
PBYTE pFile, pBits;
|
||
|
|
||
|
*ppDib = NULL;
|
||
|
hFile = CreateFile(pszFileName,
|
||
|
GENERIC_WRITE | GENERIC_READ,
|
||
|
FILE_SHARE_WRITE,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL);
|
||
|
|
||
|
if (hFile == INVALID_HANDLE_VALUE) {
|
||
|
WIA_ERROR(("ReadDIBFile, unable to open %s", pszFileName));
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
hMap = CreateFileMapping(hFile,
|
||
|
NULL,
|
||
|
PAGE_READWRITE,
|
||
|
0,
|
||
|
0,
|
||
|
NULL);
|
||
|
if (!hMap) {
|
||
|
WIA_ERROR(("ReadDIBFile, CreateFileMapping failed"));
|
||
|
goto close_hfile_exit;
|
||
|
}
|
||
|
|
||
|
pFile = (PBYTE)MapViewOfFileEx(hMap,
|
||
|
FILE_MAP_READ | FILE_MAP_WRITE,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
NULL);
|
||
|
if (pFile) {
|
||
|
PBITMAPFILEHEADER pbmFile = (PBITMAPFILEHEADER)pFile;
|
||
|
PBITMAPINFO pbmi = (PBITMAPINFO)(pFile + sizeof(BITMAPFILEHEADER));
|
||
|
|
||
|
// validate bitmap
|
||
|
if (pbmFile->bfType == 'MB') {
|
||
|
// Calculate color table size.
|
||
|
LONG bmiSize, ColorMapSize = 0;
|
||
|
|
||
|
if (pbmi->bmiHeader.biBitCount == 1) {
|
||
|
ColorMapSize = 2 - 1;
|
||
|
} else if (pbmi->bmiHeader.biBitCount == 4) {
|
||
|
ColorMapSize = 16 - 1;
|
||
|
} else if (pbmi->bmiHeader.biBitCount == 8) {
|
||
|
ColorMapSize = 256 - 1;
|
||
|
}
|
||
|
bmiSize = sizeof(BITMAPINFO) + sizeof(RGBQUAD) * ColorMapSize;
|
||
|
pBits = pFile + sizeof(BITMAPFILEHEADER) + bmiSize;
|
||
|
|
||
|
*ppDib = AllocDibFileFromBits(pBits,
|
||
|
pbmi->bmiHeader.biWidth,
|
||
|
pbmi->bmiHeader.biHeight,
|
||
|
pbmi->bmiHeader.biBitCount);
|
||
|
if (*ppDib) {
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
WIA_ERROR(("ReadDIBFile, %s is not a valid bitmap file", pszFileName));
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
WIA_ERROR(("ReadDIBFile, MapViewOfFileEx failed"));
|
||
|
goto close_hmap_exit;
|
||
|
}
|
||
|
|
||
|
UnmapViewOfFile(pFile);
|
||
|
close_hmap_exit:
|
||
|
CloseHandle(hMap);
|
||
|
close_hfile_exit:
|
||
|
CloseHandle(hFile);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* GetBmiSize
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Should never get biCompression == BI_RLE.
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
LONG _stdcall GetBmiSize(PBITMAPINFO pbmi)
|
||
|
{
|
||
|
// determine the size of bitmapinfo
|
||
|
LONG lSize = pbmi->bmiHeader.biSize;
|
||
|
|
||
|
// no color table cases
|
||
|
if (
|
||
|
(pbmi->bmiHeader.biBitCount == 24) ||
|
||
|
((pbmi->bmiHeader.biBitCount == 32) &&
|
||
|
(pbmi->bmiHeader.biCompression == BI_RGB))) {
|
||
|
|
||
|
// no colors unless stated
|
||
|
lSize += sizeof(RGBQUAD) * pbmi->bmiHeader.biClrUsed;
|
||
|
return (lSize);
|
||
|
}
|
||
|
|
||
|
// bitfields cases
|
||
|
if (((pbmi->bmiHeader.biBitCount == 32) &&
|
||
|
(pbmi->bmiHeader.biCompression == BI_BITFIELDS)) ||
|
||
|
(pbmi->bmiHeader.biBitCount == 16)) {
|
||
|
|
||
|
lSize += 3 * sizeof(RGBQUAD);
|
||
|
return (lSize);
|
||
|
}
|
||
|
|
||
|
// palette cases
|
||
|
if (pbmi->bmiHeader.biBitCount == 1) {
|
||
|
|
||
|
LONG lPal = pbmi->bmiHeader.biClrUsed;
|
||
|
|
||
|
if ((lPal == 0) || (lPal > 2)) {
|
||
|
lPal = 2;
|
||
|
}
|
||
|
|
||
|
lSize += lPal * sizeof(RGBQUAD);
|
||
|
return (lSize);
|
||
|
}
|
||
|
|
||
|
// palette cases
|
||
|
if (pbmi->bmiHeader.biBitCount == 4) {
|
||
|
|
||
|
LONG lPal = pbmi->bmiHeader.biClrUsed;
|
||
|
|
||
|
if ((lPal == 0) || (lPal > 16)) {
|
||
|
lPal = 16;
|
||
|
}
|
||
|
|
||
|
lSize += lPal * sizeof(RGBQUAD);
|
||
|
return (lSize);
|
||
|
}
|
||
|
|
||
|
// palette cases
|
||
|
if (pbmi->bmiHeader.biBitCount == 8) {
|
||
|
|
||
|
LONG lPal = pbmi->bmiHeader.biClrUsed;
|
||
|
|
||
|
if ((lPal == 0) || (lPal > 256)) {
|
||
|
lPal = 256;
|
||
|
}
|
||
|
|
||
|
lSize += lPal * sizeof(RGBQUAD);
|
||
|
return (lSize);
|
||
|
}
|
||
|
|
||
|
// error
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
INT GetColorTableSize (UINT uBitCount, UINT uCompression)
|
||
|
{
|
||
|
INT nSize;
|
||
|
|
||
|
|
||
|
switch(uBitCount)
|
||
|
{
|
||
|
case 32:
|
||
|
if (uCompression != BI_BITFIELDS)
|
||
|
{
|
||
|
nSize = 0;
|
||
|
break;
|
||
|
}
|
||
|
// fall through
|
||
|
case 16:
|
||
|
nSize = 3 * sizeof(DWORD);
|
||
|
break;
|
||
|
|
||
|
case 24:
|
||
|
nSize = 0;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
nSize = ((UINT)1 << uBitCount) * sizeof(RGBQUAD);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return(nSize);
|
||
|
}
|
||
|
|
||
|
DWORD CalcBitsSize (UINT uWidth, UINT uHeight, UINT uBitCount, UINT uPlanes, int nAlign)
|
||
|
{
|
||
|
int nAWidth,nHeight,nABits;
|
||
|
DWORD dwSize;
|
||
|
|
||
|
|
||
|
nABits = (nAlign << 3);
|
||
|
nAWidth = nABits-1;
|
||
|
|
||
|
|
||
|
// Determine the size of the bitmap based on the (nAlign) size. Convert
|
||
|
// this to size-in-bytes.
|
||
|
//
|
||
|
nHeight = uHeight * uPlanes;
|
||
|
dwSize = (DWORD)(((uWidth * uBitCount) + nAWidth) / nABits) * nHeight;
|
||
|
dwSize = dwSize * nAlign;
|
||
|
|
||
|
return(dwSize);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Converts hBitmap to a DIB
|
||
|
//
|
||
|
HGLOBAL _stdcall BitmapToDIB (HDC hdc, HBITMAP hBitmap)
|
||
|
{
|
||
|
BITMAP bm;
|
||
|
HANDLE hDib;
|
||
|
PBYTE lpDib,lpBits;
|
||
|
DWORD dwLength;
|
||
|
DWORD dwBits;
|
||
|
UINT uColorTable;
|
||
|
INT iNeedMore;
|
||
|
BOOL bDone;
|
||
|
INT nBitCount;
|
||
|
// Get the size of the bitmap. These values are used to setup the memory
|
||
|
// requirements for the DIB.
|
||
|
//
|
||
|
if(GetObject(hBitmap,sizeof(BITMAP),reinterpret_cast<PVOID>(&bm)))
|
||
|
{
|
||
|
nBitCount = bm.bmBitsPixel * bm.bmPlanes;
|
||
|
uColorTable = GetColorTableSize((UINT)nBitCount, BI_RGB);
|
||
|
dwBits = CalcBitsSize(bm.bmWidth,bm.bmHeight,nBitCount,1,sizeof(DWORD));
|
||
|
|
||
|
do
|
||
|
{
|
||
|
bDone = TRUE;
|
||
|
|
||
|
dwLength = dwBits + sizeof(BITMAPINFOHEADER) + uColorTable;
|
||
|
|
||
|
|
||
|
// Create the DIB. First, to the size of the bitmap.
|
||
|
//
|
||
|
if(hDib = GlobalAlloc(GHND,dwLength))
|
||
|
{
|
||
|
if(lpDib = reinterpret_cast<PBYTE>(GlobalLock(hDib)))
|
||
|
{
|
||
|
((LPBITMAPINFOHEADER)lpDib)->biSize = sizeof(BITMAPINFOHEADER);
|
||
|
((LPBITMAPINFOHEADER)lpDib)->biWidth = (DWORD)bm.bmWidth;
|
||
|
((LPBITMAPINFOHEADER)lpDib)->biHeight = (DWORD)bm.bmHeight;
|
||
|
((LPBITMAPINFOHEADER)lpDib)->biPlanes = 1;
|
||
|
((LPBITMAPINFOHEADER)lpDib)->biBitCount = (WORD)nBitCount;
|
||
|
((LPBITMAPINFOHEADER)lpDib)->biCompression = 0;
|
||
|
((LPBITMAPINFOHEADER)lpDib)->biSizeImage = 0;
|
||
|
((LPBITMAPINFOHEADER)lpDib)->biXPelsPerMeter = 0;
|
||
|
((LPBITMAPINFOHEADER)lpDib)->biYPelsPerMeter = 0;
|
||
|
((LPBITMAPINFOHEADER)lpDib)->biClrUsed = 0;
|
||
|
((LPBITMAPINFOHEADER)lpDib)->biClrImportant = 0;
|
||
|
|
||
|
|
||
|
// Get the size of the bitmap.
|
||
|
// The biSizeImage contains the bytes
|
||
|
// necessary to store the DIB.
|
||
|
//
|
||
|
GetDIBits(hdc,hBitmap,0,bm.bmHeight,NULL,(LPBITMAPINFO)lpDib,DIB_RGB_COLORS);
|
||
|
|
||
|
iNeedMore = ((LPBITMAPINFOHEADER)lpDib)->biSizeImage - dwBits;
|
||
|
|
||
|
if ( iNeedMore > 0 )
|
||
|
{
|
||
|
dwBits = dwBits + (((iNeedMore + 3) / 4)*4);
|
||
|
bDone = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
lpBits = lpDib+sizeof(BITMAPINFOHEADER)+uColorTable;
|
||
|
GetDIBits(hdc,hBitmap,0,bm.bmHeight,lpBits,(LPBITMAPINFO)lpDib,DIB_RGB_COLORS);
|
||
|
|
||
|
GlobalUnlock(hDib);
|
||
|
|
||
|
return(hDib);
|
||
|
}
|
||
|
|
||
|
GlobalUnlock(hDib);
|
||
|
}
|
||
|
|
||
|
GlobalFree(hDib);
|
||
|
}
|
||
|
}
|
||
|
while (!bDone);
|
||
|
}
|
||
|
|
||
|
return(NULL);
|
||
|
|
||
|
}
|
||
|
|
||
|
}; // End Namespace Util
|
||
|
|
||
|
|