windows-nt/Source/XPSP1/NT/printscan/ui/cimage/util.cpp

465 lines
12 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*******************************************************************************
*
* (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