📄 dib.c
字号:
/* get a proper-sized buffer for header, color table and bits */
GlobalUnlock(hDIB);
hDIBtmp = GlobalReAlloc(hDIB, lpbi->biSize + nNumColors *
sizeof(RGBQUAD) + lpbi->biSizeImage, 0);
if (!hDIBtmp) /* can't resize buffer for loading */
goto ErrExitNoUnlock; /* MPB */
else
hDIB = hDIBtmp;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
/* read the color table */
ReadFile (hFile, (LPSTR)(lpbi) + lpbi->biSize,
nNumColors * sizeof(RGBQUAD), &dwRead, NULL);
/* offset to the bits from start of DIB header */
offBits = lpbi->biSize + nNumColors * sizeof(RGBQUAD);
/* If the bfOffBits field is non-zero, then the bits might *not* be */
/* directly following the color table in the file. Use the value in */
/* bfOffBits to seek the bits. */
if (bmfHeader.bfOffBits != 0L)
SetFilePointer(hFile, bmfHeader.bfOffBits, NULL, FILE_BEGIN);
if (ReadFile(hFile, (LPSTR)lpbi + offBits, lpbi->biSizeImage, &dwRead,
NULL))
goto OKExit;
ErrExit:
GlobalUnlock(hDIB);
ErrExitNoUnlock:
GlobalFree(hDIB);
return NULL;
OKExit:
GlobalUnlock(hDIB);
return hDIB;
}
/*************************************************************************
*
* LoadDIB()
*
* Loads the specified DIB from a file, allocates memory for it,
* and reads the disk file into the memory.
*
*
* Parameters:
*
* LPSTR lpFileName - specifies the file to load a DIB from
*
* Returns: A handle to a DIB, or NULL if unsuccessful.
*
* NOTE: The DIB API were not written to handle OS/2 DIBs; This
* function will reject any file that is not a Windows DIB.
*
* History: Date Author Reason
* 9/15/91 Mark Bader Based on DIBVIEW
*
*************************************************************************/
HBITMAP LoadDIB(LPSTR lpFileName)
{
HBITMAP hDIB;
HANDLE hFile;
if ((hFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL)) != INVALID_HANDLE_VALUE)
{
hDIB = ReadDIBFile(hFile);
CloseHandle(hFile);
return hDIB;
}
else
return NULL;
}
/*************************************************************************
*
* SaveBmpFromDDB()
*
* Saves the specified DDB into the specified file name on disk.
*
*************************************************************************/
BOOL
SaveBmpFromDDB(HDC hDC, HBITMAP hBmp, PSTR pszFileName)
{
int hFile;
OFSTRUCT ofReOpenBuff;
HBITMAP hTmpBmp, hBmpOld;
BOOL bSuccess;
BITMAPFILEHEADER bfh;
PBITMAPINFO pbmi;
PBYTE pBits;
BITMAPINFO bmi;
PBYTE pjTmp, pjTmpBmi;
ULONG sizBMI;
bSuccess = TRUE;
#if 0
if (ghPal) {
SelectPalette(hDC, ghPal, FALSE);
RealizePalette(hDC);
}
#endif
if (!hBmp) {
return FALSE;
}
//
// Let the graphics engine to retrieve the dimension of the bitmap for us
// GetDIBits uses the size to determine if it's BITMAPCOREINFO or BITMAPINFO
// if BitCount != 0, color table will be retrieved
//
bmi.bmiHeader.biSize = 0x28; // GDI need this to work
bmi.bmiHeader.biBitCount = 0; // don't get the color table
if ((GetDIBits(hDC, hBmp, 0, 0, (LPSTR)NULL, &bmi, DIB_RGB_COLORS)) == 0) {
return FALSE;
}
//
// Now that we know the size of the image, alloc enough memory to retrieve
// the actual bits
//
if ((pBits = (PBYTE)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
bmi.bmiHeader.biSizeImage)) == NULL) {
return FALSE;
}
//
// Note: 24 bits per pixel has no color table. So, we don't have to
// allocate memory for retrieving that. Otherwise, we do.
//
pbmi = &bmi; // assume no color table
switch (bmi.bmiHeader.biBitCount) {
case 24: // has color table
sizBMI = sizeof(BITMAPINFOHEADER);
break;
case 16:
case 32:
sizBMI = sizeof(BITMAPINFOHEADER)+sizeof(DWORD)*3;
break;
default:
sizBMI = sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*(1<<bmi.bmiHeader.biBitCount);
break;
}
//
// Allocate memory for color table if it is not 24bpp...
//
if (sizBMI != sizeof(BITMAPINFOHEADER)) {
ULONG sizTmp;
//
// I need more memory for the color table
//
if ((pbmi = (PBITMAPINFO)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizBMI )) == NULL) {
bSuccess = FALSE;
goto ErrExit1;
}
//
// Now that we've a bigger chunk of memory, let's copy the Bitmap
// info header data over
//
pjTmp = (PBYTE)pbmi;
pjTmpBmi = (PBYTE)&bmi;
sizTmp = sizeof(BITMAPINFOHEADER);
while(sizTmp--)
{
*(((PBYTE)pjTmp)++) = *((pjTmpBmi)++);
}
}
//
// Let's open the file and get ready for writing
//
if ((hFile = OpenFile(pszFileName, (LPOFSTRUCT)&ofReOpenBuff,
OF_CREATE | OF_WRITE)) == -1) {
goto ErrExit2;
}
//
// But first, fill in the info for the BitmapFileHeader
//
bfh.bfType = 0x4D42; // 'BM'
bfh.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizBMI+
pbmi->bmiHeader.biSizeImage;
bfh.bfReserved1 =
bfh.bfReserved2 = 0;
bfh.bfOffBits = sizeof(BITMAPFILEHEADER)+sizBMI;
//
// Write out the file header now
//
if (_lwrite(hFile, (LPSTR)&bfh, sizeof(BITMAPFILEHEADER)) == -1) {
bSuccess = FALSE;
goto ErrExit3;
}
//
// Bitmap can't be selected into a DC when calling GetDIBits
// Assume that the hDC is the DC where the bitmap would have been selected
// if indeed it has been selected
//
if (hTmpBmp = CreateCompatibleBitmap(hDC, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight)) {
hBmpOld = SelectObject(hDC, hTmpBmp);
if ((GetDIBits(hDC, hBmp, 0, pbmi->bmiHeader.biHeight, (LPSTR)pBits, pbmi, DIB_RGB_COLORS))==0){
bSuccess = FALSE;
goto ErrExit4;
}
} else {
bSuccess = FALSE;
goto ErrExit3;
}
//
// Now write out the BitmapInfoHeader and color table, if any
//
if (_lwrite(hFile, (LPSTR)pbmi, sizBMI) == -1) {
bSuccess = FALSE;
goto ErrExit4;
}
//
// write the bits also
//
if (_lwrite(hFile, (LPSTR)pBits, pbmi->bmiHeader.biSizeImage) == -1) {
bSuccess = FALSE;
goto ErrExit4;
}
ErrExit4:
SelectObject(hDC, hBmpOld);
DeleteObject(hTmpBmp);
ErrExit3:
_lclose(hFile);
ErrExit2:
GlobalFree(pbmi);
ErrExit1:
GlobalFree(pBits);
return bSuccess;
}
/*************************************************************************
*
* SaveDIB()
*
* Saves the specified DIB into the specified file name on disk. No
* error checking is done, so if the file already exists, it will be
* written over.
*
* Parameters:
*
* HDIB hDib - Handle to the dib to save
*
* LPSTR lpFileName - pointer to full pathname to save DIB under
*
* Return value: 0 if successful, or one of:
* ERR_INVALIDHANDLE
* ERR_OPEN
* ERR_LOCK
*
* History:
*
* NOTE: The DIB API were not written to handle OS/2 DIBs, so this
* function will not save a file if it is not a Windows DIB.
*
* History: Date Author Reason
* 9/15/91 Mark Bader Taken from DIBVIEW (which was taken
* from SHOWDIB)
* 1/30/92 Mark Bader Fixed problem of writing too many
* bytes to the file
* 6/24/92 Mark Bader Added check for OS/2 DIB
* 2/1/94 Hung Nguyen Changed file APIs to Win32 APIs
*
*************************************************************************/
BOOL SaveDIB(HBITMAP hDib, LPSTR lpFileName)
{
BITMAPFILEHEADER bmfHdr; /* Header for Bitmap file */
LPBITMAPINFOHEADER lpBI; /* Pointer to DIB info structure */
HANDLE fh; /* file handle for opened file */
DWORD dwDIBSize;
DWORD dwWritten;
if (!hDib)
return FALSE;
fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (fh == INVALID_HANDLE_VALUE)
return FALSE;
/* Get a pointer to the DIB memory, the first of which contains */
/* a BITMAPINFO structure */
lpBI = (LPBITMAPINFOHEADER)GlobalLock(hDib);
if (!lpBI)
{
CloseHandle(fh);
return FALSE;
}
/* Check to see if we're dealing with an OS/2 DIB. If so, don't */
/* save it because our functions aren't written to deal with these */
/* DIBs. */
if (lpBI->biSize != sizeof(BITMAPINFOHEADER))
{
GlobalUnlock(hDib);
CloseHandle(fh);
return FALSE;
}
/* Fill in the fields of the file header */
/* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
bmfHdr.bfType = DIB_HEADER_MARKER; /* "BM" */
/* Calculating the size of the DIB is a bit tricky (if we want to */
/* do it right). The easiest way to do this is to call GlobalSize() */
/* on our global handle, but since the size of our global memory may have */
/* been padded a few bytes, we may end up writing out a few too */
/* many bytes to the file (which may cause problems with some apps, */
/* like HC 3.0). */
/* */
/* So, instead let's calculate the size manually. */
/* */
/* To do this, find size of header plus size of color table. Since the */
/* first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains */
/* the size of the structure, let's use this. */
/* Partial Calculation */
dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPSTR)lpBI);
/* Now calculate the size of the image */
/* It's an RLE bitmap, we can't calculate size, so trust the biSizeImage */
/* field */
if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
dwDIBSize += lpBI->biSizeImage;
else
{
DWORD dwBmBitsSize; /* Size of Bitmap Bits only */
/* It's not RLE, so size is Width (DWORD aligned) * Height */
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) *
lpBI->biHeight;
dwDIBSize += dwBmBitsSize;
/* Now, since we have calculated the correct size, why don't we */
/* fill in the biSizeImage field (this will fix any .BMP files which */
/* have this field incorrect). */
lpBI->biSizeImage = dwBmBitsSize;
}
/* Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER) */
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
/* Now, calculate the offset the actual bitmap bits will be in */
/* the file -- It's the Bitmap file header plus the DIB header, */
/* plus the size of the color table. */
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize +
PaletteSize((LPSTR)lpBI);
/* Write the file header */
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
/* Write the DIB header and the bits -- use local version of */
/* MyWrite, so we can write more than 32767 bytes of data */
WriteFile(fh, (LPSTR)lpBI, dwDIBSize, &dwWritten, NULL);
GlobalUnlock(hDib);
CloseHandle(fh);
if (dwWritten == 0)
return FALSE; /* oops, something happened in the write */
else
return TRUE; /* Success code */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -