📄 dibit.c
字号:
* PURPOSE : Given a BITMAPINFOHEADER, create a palette based on
* the color table.
*
* *
* RETURNS : non-zero - handle of a corresponding palette
* zero - unable to create palette
* *
****************************************************************************/
HPALETTE PASCAL NEAR MakeDIBPalette(LPBITMAPINFOHEADER lpInfo)
{
NPLOGPALETTE npPal;
RGBQUAD far *lpRGB;
HPALETTE hLogPal;
WORD i;
/* since biClrUsed field was filled during the loading of the DIB,
** we know it contains the number of colors in the color table.
*/
if (lpInfo->biClrUsed)
{
npPal = (NPLOGPALETTE)LocalAlloc(LMEM_FIXED, sizeof(LOGPALETTE) +
(WORD)lpInfo->biClrUsed * sizeof(PALETTEENTRY));
if (!npPal)
return(FALSE);
npPal->palVersion = 0x300;
npPal->palNumEntries = (WORD)lpInfo->biClrUsed;
/* get pointer to the color table */
lpRGB = (RGBQUAD FAR *)((LPSTR)lpInfo + lpInfo->biSize);
/* copy colors from the color table to the LogPalette structure */
for (i = 0; i < (WORD)lpInfo->biClrUsed; i++, lpRGB++)
{
npPal->palPalEntry[i].peRed = lpRGB->rgbRed;
npPal->palPalEntry[i].peGreen = lpRGB->rgbGreen;
npPal->palPalEntry[i].peBlue = lpRGB->rgbBlue;
npPal->palPalEntry[i].peFlags = 0;
}
hLogPal = CreatePalette((LPLOGPALETTE)npPal);
LocalFree((HANDLE)npPal);
return(hLogPal);
}
/* 24-bit DIB with no color table. return default palette. Another
** option would be to create a 256 color "rainbow" palette to provide
** some good color choices.
*/
else
return(GetStockObject(DEFAULT_PALETTE));
}
/****************************************************************************
* *
* FUNCTION : PaintDIB(hWnd) *
* *
* PURPOSE : Paint the currently loaded DIB using the options chosen
* by the user.
* *
* RETURNS : None.
* *
****************************************************************************/
void PASCAL NEAR PaintDIB(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hDC;
RECT Rectangle;
LPBITMAPINFOHEADER lpInfo;
LPBITMAPINFOHEADER lpHeader;
HPALETTE hOldPal;
WORD wDIBUse;
hDC = BeginPaint(hWnd, &ps);
lpInfo = (LPBITMAPINFOHEADER) GlobalLock(hDIBInfo);
/* if using a palette for drawing and there is actually
** a color table, then get a palette and realize it.
*/
if (wPalOp && lpInfo->biClrUsed)
{
if (!hPalette)
hPalette = MakeDIBPalette(lpInfo);
if (!hPalette)
{
MessageBox(hWnd, "Can't create palette", "Error", MB_ICONSTOP | MB_OK);
goto ExitTime;
}
hOldPal = SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
/* if using DIB_PAL_COLORS and the bitmap is not 24-bit,
** then use a header with a color table of indices.
*/
if (wPalOp == IDM_PALIND && (lpInfo->biBitCount != 24))
{
if (!hPalHeader)
{
hPalHeader = MakeIndexHeader(lpInfo);
}
if (!hPalHeader)
{
MessageBox(hWnd, "Can't create Indexed color table", "Error", MB_ICONSTOP | MB_OK);
goto ExitTime;
}
lpHeader = (LPBITMAPINFOHEADER) GlobalLock(hPalHeader);
wDIBUse = DIB_PAL_COLORS;
}
else
{
lpHeader = lpInfo;
wDIBUse = DIB_RGB_COLORS;
}
}
else
{
lpHeader = lpInfo;
wDIBUse = DIB_RGB_COLORS;
}
switch (wOperation)
{
case IDM_SETDIB:
//error message if can't create
if (!hDDBitmap)
{
hMemDC = CreateCompatibleDC(hDC);
hDDBitmap = CreateCompatibleBitmap(hDC,
(WORD)lpInfo->biWidth, (WORD)lpInfo->biHeight);
SetDIBits(hDC, hDDBitmap, 0, (WORD)lpInfo->biHeight,
(LPSTR)lpInfo + offBits,
(LPBITMAPINFO)lpHeader, wDIBUse);
hOldBitmap = SelectObject(hMemDC, hDDBitmap);
}
BitBlt(hDC, 0, 0, (WORD)lpInfo->biWidth, (WORD)lpInfo->biHeight,
hMemDC, 0, 0, SRCCOPY);
break;
case IDM_TODEV:
SetDIBitsToDevice(hDC, 0, 0, (WORD)lpInfo->biWidth, (WORD)lpInfo->biHeight,
0, 0, 0, (WORD)lpInfo->biHeight,
(LPSTR)lpInfo + offBits, (LPBITMAPINFO)lpHeader, wDIBUse);
break;
case IDM_STRETCH:
/* get dimensions of window and stretch to fit */
GetClientRect(hWnd, (LPRECT)&Rectangle);
StretchDIBits(hDC, 0, 0, Rectangle.right, Rectangle.bottom,
0, 0, (WORD)lpInfo->biWidth, (WORD)lpInfo->biHeight,
(LPSTR)lpInfo + offBits,
(LPBITMAPINFO)lpHeader, wDIBUse, SRCCOPY);
/* NOTE: because driver does not do the StretchDIB
** itself, this is not a fast operation.
** internally it converts to CreateDIBitmap
** followed by a StretchBlt
*/
break;
}
/* clean up any palette work */
if (wPalOp)
{
SelectPalette(hDC, hOldPal, FALSE);
if (wPalOp == IDM_PALIND)
GlobalUnlock(hPalHeader);
}
ExitTime:
GlobalUnlock(hDIBInfo);
EndPaint(hWnd, &ps);
}
/****************************************************************************
* *
* FUNCTION : ReadDIB(hWnd) *
* *
* PURPOSE : Reads a DIB from a file, obtains a handle to it's *
* BITMAPINFO struct. and loads the DIB. *
* *
* RETURNS : TRUE - DIB loads ok *
* FALSE - otherwise *
* *
****************************************************************************/
int ReadDIB(HWND hWnd)
{
unsigned fh;
LPBITMAPINFOHEADER lpbi;
OFSTRUCT of;
BITMAPFILEHEADER bf;
WORD nNumColors;
WORD result = FALSE; /* assume failure */
/* Open the file and get a handle to it's BITMAPINFO */
fh = OpenFile (achFileName, &of, OF_READ);
if (fh == -1) {
wsprintf(str,"Can't open file '%ls'", (LPSTR)achFileName);
MessageBox(hWnd, str, "Error", MB_ICONSTOP | MB_OK);
return (FALSE);
}
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIBInfo);
/* read the BITMAPFILEHEADER */
if (sizeof (bf) != _lread (fh, (LPSTR)&bf, sizeof (bf)))
goto ErrExit;
if (bf.bfType != 0x4d42) /* 'BM' */
goto ErrExit;
if (sizeof(BITMAPINFOHEADER) != _lread (fh, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)))
goto ErrExit;
/* !!!!! for now, don't even deal with CORE headers */
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
goto ErrExit;
if (!(nNumColors = (WORD)lpbi->biClrUsed))
{
/* no color table for 24-bit, default size otherwise */
if (lpbi->biBitCount != 24)
nNumColors = 1 << lpbi->biBitCount; /* standard size table */
}
/* fill in some default values if they are zero */
if (lpbi->biClrUsed == 0)
lpbi->biClrUsed = (DWORD)nNumColors;
if (lpbi->biSizeImage == 0)
{
lpbi->biSizeImage = ((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3)
* lpbi->biHeight;
}
/* get a proper-sized buffer for header, color table and bits */
GlobalUnlock(hDIBInfo);
hDIBInfo = GlobalReAlloc(hDIBInfo, lpbi->biSize +
nNumColors * sizeof(RGBQUAD) +
lpbi->biSizeImage, 0);
if (!hDIBInfo) /* can't resize buffer for loading */
goto ErrExit2;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIBInfo);
/* read the color table */
_lread (fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD));
/* offset to the bits from start of DIB header */
offBits = (WORD)lpbi->biSize + nNumColors * sizeof(RGBQUAD);
if (bf.bfOffBits != 0L)
{
_llseek(fh,bf.bfOffBits,SEEK_SET);
}
if (lpbi->biSizeImage == lread(fh, (LPSTR)lpbi + offBits, lpbi->biSizeImage))
result = TRUE;
ErrExit:
_lclose(fh);
GlobalUnlock(hDIBInfo);
ErrExit2:
return(result);
}
/**************** PRIVATE ROUTINE TO READ MORE THAN 64K *********************/
/****************************************************************************
* *
* FUNCTION : lread(int fh, VOID FAR *pv, DWORD ul) *
* *
* PURPOSE : Reads data in steps of 32k till all the data has been read.*
* *
* RETURNS : 0 - If read did not proceed correctly. *
* number of bytes read otherwise. *
* *
****************************************************************************/
DWORD PASCAL lread (int fh, VOID far *pv, DWORD ul)
{
DWORD ulT = ul;
// BYTE huge *hp = pv;
BYTE *hp = pv;
while (ul > (DWORD)MAXREAD) {
if (_lread(fh, (LPSTR)hp, (WORD)MAXREAD) != MAXREAD)
return 0;
ul -= MAXREAD;
hp += MAXREAD;
}
if (_lread(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
return 0;
return ulT;
}
/**************** PRIVATE ROUTINE TO READ MORE THAN 64K *********************/
/****************************************************************************
* *
* FUNCTION : InitDIB(hWnd) *
* *
* PURPOSE : cleans up old DIB info, reads new DIB from file,
* resizes window for new DIB
* *
* RETURNS : TRUE - DIB loads ok *
* FALSE - otherwise *
* *
****************************************************************************/
int InitDIB(HWND hWnd)
{
LPBITMAPINFOHEADER lpbi;
RECT Rectangle;
/* if there was an old DIB, free it up */
if (bDIBLoaded)
{
if (hDDBitmap)
{
SelectObject(hMemDC, hOldBitmap);
DeleteDC(hMemDC);
DeleteObject(hDDBitmap);
hDDBitmap = NULL;
}
bDIBLoaded = FALSE;
if (hPalette)
{
DeleteObject(hPalette);
hPalette = 0;
}
if (hPalHeader)
{
GlobalFree(hPalHeader);
hPalHeader = NULL;
}
}
/* load the DIB from the file */
if (!ReadDIB(hWnd))
{
MessageBox(hWnd, "Error attempting to read DIB", "Error", MB_ICONSTOP | MB_OK);
return(FALSE);
}
bDIBLoaded = TRUE; /* there is a DIB loaded now */
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIBInfo);
SetWindowText(hWnd, achFileName);
Rectangle.left = 0;
Rectangle.top = 0;
Rectangle.right = (WORD)lpbi->biWidth;
Rectangle.bottom = (WORD)lpbi->biHeight;
GlobalUnlock(hDIBInfo);
/* Compute the size of the window rectangle based on the given
* client rectangle size and the window style, then size the
* window. Do not deal with possibility of more than one menu line.
*/
AdjustWindowRect (&Rectangle, WS_OVERLAPPEDWINDOW, TRUE);
SetWindowPos (hWnd, (HWND)NULL, 0, 0,
Rectangle.right - Rectangle.left,
Rectangle.bottom - Rectangle.top + 1,
SWP_NOMOVE | SWP_NOZORDER);
GetClientRect(hWnd, &Rectangle);
return(TRUE);
}
/****************************************************************************
FUNCTION: About(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages for "About" dialog box
MESSAGES:
WM_INITDIALOG - initialize dialog box
WM_COMMAND - Input received
COMMENTS:
No initialization is needed for this particular dialog box, but TRUE
must be returned to Windows.
Wait for user to click on "Ok" button, then close the dialog box.
****************************************************************************/
//BOOL FAR PASCAL __export About(hDlg, message, wParam, lParam)
BOOL APIENTRY About(hDlg, message, wParam, lParam)
HWND hDlg; /* window handle of the dialog box */
unsigned message; /* type of message */
WORD wParam; /* message-specific information */
LONG lParam;
{
switch (message) {
case WM_INITDIALOG: /* message: initialize dialog box */
return (TRUE);
case WM_COMMAND: /* message: received a command */
if (wParam == IDOK /* "OK" box selected? */
|| wParam == IDCANCEL) { /* System menu close command? */
EndDialog(hDlg, TRUE); /* Exits the dialog box */
return (TRUE);
}
break;
}
return (FALSE); /* Didn't process a message */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -