📄 dibapi.cpp
字号:
*
\****************************************************************************/
HBITMAP DIBToDIBSection(LPSTR lpDIB)
{
LPSTR lpSourceBits;
HDC hDC = NULL, hSourceDC;
HBITMAP hSourceBitmap, hOldSourceBitmap;
DWORD dwSourceBitsSize;
LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)lpDIB;
if (! lpSrcDIB)
return NULL;
// Gonna use DIBSections and BitBlt() to do the conversion, so make 'em
hDC = GetDC( NULL );
hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 );
hSourceDC = CreateCompatibleDC( hDC );
// Flip the bits on the source DIBSection to match the source DIB
dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpSrcDIB->bmiHeader));
memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize );
// Select DIBSections into DCs
hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap );
// Set the color tables for the DIBSections
if( lpSrcDIB->bmiHeader.biBitCount <= 8 )
SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors );
// Clean up and delete the DCs
SelectObject( hSourceDC, hOldSourceBitmap );
DeleteDC( hSourceDC );
ReleaseDC( NULL, hDC );
// Flush the GDI batch, so we can play with the bits
GdiFlush();
return hSourceBitmap;
}
// Create DIBSECTION from DIB
HBITMAP DIBToDIBSection(HDIB hDIB)
{
HBITMAP hSourceBitmap;
// Get DIB pointer
if (! hDIB)
return NULL;
LPSTR lpSrcDIB = (LPSTR)GlobalLock(hDIB);
if (! lpSrcDIB)
return NULL;
hSourceBitmap = DIBToDIBSection(lpSrcDIB);
// final cleanup
GlobalUnlock(hDIB);
return hSourceBitmap;
}
/****************************************************************************
*
* FUNCTION: DIBSectionToDIB
*
* PURPOSE: Create DIB from DIBSECTION
*
* PARAMS: HBITMAP - handle of DIBSECTION, or NULL for failure
*
* RETURNS: HBITMAP hBitmap - DIB handle
*
\****************************************************************************/
HDIB DIBSectionToDIB(HBITMAP hBitmap)
{
HDC hDC = NULL, hSourceDC;
HBITMAP hOldSourceBitmap;
HANDLE hNewDIB;
LPBITMAPINFO lpbmi = NULL;
DWORD dwSize;
DIBSECTION ds;
DWORD dwColorNum;
// get DIB info
GetObject(hBitmap, sizeof(DIBSECTION), &ds);
dwColorNum = ds.dsBmih.biClrUsed;
if (dwColorNum == 0 && ds.dsBmih.biBitCount <= 8)
dwColorNum = 1 << ds.dsBmih.biBitCount;
// Allocate and fill out a BITMAPINFO struct for the new DIB
dwSize = sizeof(BITMAPINFOHEADER) + (dwColorNum * sizeof(RGBQUAD)) + ds.dsBmih.biSizeImage;
hNewDIB = GlobalAlloc(GHND, dwSize);
if (! hNewDIB)
return NULL;
lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB);
if (! lpbmi)
return NULL;
lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
lpbmi->bmiHeader.biWidth = ds.dsBm.bmWidth;
lpbmi->bmiHeader.biHeight = ds.dsBm.bmHeight;
lpbmi->bmiHeader.biPlanes = 1;
lpbmi->bmiHeader.biBitCount = ds.dsBmih.biBitCount;
lpbmi->bmiHeader.biCompression = ds.dsBmih.biCompression;
lpbmi->bmiHeader.biSizeImage = ds.dsBmih.biSizeImage;
lpbmi->bmiHeader.biXPelsPerMeter = ds.dsBmih.biXPelsPerMeter;
lpbmi->bmiHeader.biYPelsPerMeter = ds.dsBmih.biYPelsPerMeter;
lpbmi->bmiHeader.biClrUsed = ds.dsBmih.biClrUsed;
lpbmi->bmiHeader.biClrImportant = ds.dsBmih.biClrImportant;
// get DC for operation
hDC = GetDC( NULL );
// get DIB bits
if (! GetDIBits(hDC,
hBitmap,
0L,
(DWORD)ds.dsBm.bmHeight,
(LPSTR)lpbmi + (WORD)lpbmi->bmiHeader.biSize + (dwColorNum*sizeof(RGBQUAD)),
(LPBITMAPINFO)lpbmi,
(DWORD)DIB_RGB_COLORS))
{
GlobalUnlock(hNewDIB);
ReleaseDC(NULL,hDC);
return NULL;
}
// memory DC
hSourceDC = CreateCompatibleDC( hDC );
// Select DIBSections into DCs
hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hBitmap );
// Fill in the color table from DIBSection
if( lpbmi->bmiHeader.biBitCount <= 8 )
GetDIBColorTable( hSourceDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors );
// Clean up and delete the DCs
SelectObject( hSourceDC, hOldSourceBitmap );
DeleteDC( hSourceDC );
ReleaseDC( NULL, hDC );
GlobalUnlock(hNewDIB);
return hNewDIB;
}
/*************************************************************************
*
* CopyHandle()
*
* Parameters:
*
* HANDLE h - source handle
*
* Return Value:
*
* HANDLE - duplicated handle
*
* Description:
*
* Copy memory handle to another
************************************************************************/
HANDLE CopyHandle(HANDLE h)
{
if (h == NULL)
return NULL;
DWORD dwLen = ::GlobalSize((HGLOBAL)h);
HANDLE hCopy = ::GlobalAlloc(GHND, dwLen);
if (hCopy == NULL)
return NULL;
void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
void* lp = ::GlobalLock((HGLOBAL) h);
::CopyMemory(lpCopy, lp, dwLen);
::GlobalUnlock(hCopy);
::GlobalUnlock(h);
return hCopy;
}
/*************************************************************************
*
* ChangeDIBFormat()
*
* Parameter:
*
* HDIB - handle to packed-DIB in memory
*
* WORD - desired bits per pixel
*
* DWORD - desired compression format
*
* Return Value:
*
* HDIB - handle to the new DIB if successful, else NULL
*
* Description:
*
* This function will convert the bits per pixel and/or the compression
* format of the specified DIB. Note: If the conversion was unsuccessful,
* we return NULL. The original DIB is left alone. Don't use code like the
* following:
*
* hMyDIB = ChangeDIBFormat(hMyDIB, 8, BI_RLE4);
*
* The conversion will fail, but hMyDIB will now be NULL and the original
* DIB will now hang around in memory. We could have returned the old
* DIB, but we wanted to allow the programmer to check whether this
* conversion succeeded or failed.
*
************************************************************************/
HDIB ChangeDIBFormat(HDIB hDIB, WORD wBitCount, DWORD dwCompression)
{
HBITMAP hBitmap; // Handle to bitmap
HDIB hNewDIB = NULL; // Handle to new DIB
HPALETTE hPal; // Handle to palette
// Check for a valid DIB handle
if (!hDIB)
return NULL;
// Save the old DIB's palette
hPal = CreateDIBPalette(hDIB);
if (hPal == NULL)
hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
// Convert old DIB to a bitmap
hBitmap = DIBToBitmap(hDIB, hPal);
if (!hBitmap)
{
DeleteObject(hPal);
return NULL;
}
// Change bitmap format
hNewDIB = ChangeBitmapFormat(hBitmap, wBitCount, dwCompression, hPal);
// Clean up and return
DeleteObject(hBitmap);
DeleteObject(hPal);
return hNewDIB;
}
/*************************************************************************
*
* ChangeBitmapFormat()
*
* Parameter:
*
* HBITMAP - handle to a bitmap
*
* WORD - desired bits per pixel
*
* DWORD - desired compression format
*
* HPALETTE - handle to palette
*
* Return Value:
*
* HDIB - handle to the new DIB if successful, else NULL
*
* Description:
*
* This function will convert a bitmap to the specified bits per pixel
* and compression format. The bitmap and it's palette will remain
* after calling this function.
*
************************************************************************/
HDIB ChangeBitmapFormat (HBITMAP hbm, WORD biBits, DWORD biCompression, HPALETTE hpal)
{
BITMAP bm;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
DWORD dwLen;
HANDLE hdib;
HANDLE h;
HDC hdc;
if (!hbm)
return NULL;
if (hpal == NULL)
hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
GetObject(hbm,sizeof(bm),(LPSTR)&bm);
if (biBits == 0)
{
biBits = bm.bmPlanes * bm.bmBitsPixel;
// make sure bits per pixel is valid
if (biBits <= 1)
biBits = 1;
else if (biBits <= 4)
biBits = 4;
else if (biBits <= 8)
biBits = 8;
else // if greater than 8-bit, force to 24-bit
biBits = 24;
}
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = biBits;
bi.biCompression = biCompression;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwLen = bi.biSize + PaletteSize((LPSTR)&bi);
hdc = GetDC(NULL);
HPALETTE hpalT = SelectPalette(hdc,hpal,FALSE);
RealizePalette(hdc);
hdib = GlobalAlloc(GHND,dwLen);
if (!hdib)
{
SelectPalette(hdc,hpalT,FALSE);
ReleaseDC(NULL,hdc);
return NULL;
}
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
*lpbi = bi;
/* call GetDIBits with a NULL lpBits param, so it will calculate the
* biSizeImage field for us
*/
GetDIBits(hdc, hbm, 0L, (DWORD)bi.biHeight,
(LPSTR)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);
bi = *lpbi;
GlobalUnlock(hdib);
/* If the driver did not fill in the biSizeImage field, make one up */
if (bi.biSizeImage == 0)
{
bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;
if (biCompression != BI_RGB)
bi.biSizeImage = (bi.biSizeImage * 3) / 2;
}
/* realloc the buffer big enough to hold all the bits */
dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + bi.biSizeImage;
if (h = GlobalReAlloc(hdib,dwLen,0))
hdib = h;
else
{
GlobalFree(hdib);
hdib = NULL;
SelectPalette(hdc,hpalT,FALSE);
ReleaseDC(NULL,hdc);
return hdib;
}
/* call GetDIBits with a NON-NULL lpBits param, and actualy get the
* bits this time
*/
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
if (! GetDIBits(hdc,
hbm,
0L,
(DWORD)bi.biHeight,
(LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi),
(LPBITMAPINFO)lpbi,
(DWORD)DIB_RGB_COLORS))
{
GlobalUnlock(hdib);
hdib = NULL;
SelectPalette(hdc,hpalT,FALSE);
ReleaseDC(NULL,hdc);
return NULL;
}
bi = *lpbi;
GlobalUnlock(hdib);
SelectPalette(hdc,hpalT,FALSE);
ReleaseDC(NULL,hdc);
return hdib;
}
/*************************************************************************
*
* DIBToBitmap()
*
* Parameters:
*
* HDIB hDIB - specifies the DIB to convert
*
* HPALETTE hPal - specifies the palette to use with the bitmap
*
* Return Value:
*
* HBITMAP - identifies the device-dependent bitmap
*
* Description:
*
* This function creates a bitmap from a DIB using the specified palette.
* If no palette is specified, default is used.
*
* NOTE:
*
* The bitmap returned from this funciton is always a bitmap compatible
* with the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -