📄 pjaimage.cpp
字号:
// Note :
// Uses the 'True Mask' method
// Modified from code found at http://www.codeguru.com/bitmap/CISBitmap.shtml
// original author Paul Reynolds (Paul.Reynolds@cmgroup.co.uk)
//
/////////////////////////////////////////////////////////////////////////////
void CPJAImage::DrawTransparent(CDC *pToDC, int w, int h, CDC *pFromDC)
{
// handle for the grayscale image
HBITMAP Gray = NULL;
CDC MonoDC;
MonoDC.CreateCompatibleDC(pToDC);
int savedToDC = pToDC->SaveDC();
int savedFromDC = pFromDC->SaveDC();
int savedMonoDC = MonoDC.SaveDC();
pToDC->SetBkColor(RGB(255, 255, 255));
pToDC->SetTextColor(RGB(0, 0, 0));
pFromDC->SetBkColor(m_TransparentColour);
// Create the mask
CBitmap MonoDCbmp;
MonoDCbmp.CreateBitmap(w, h, 1, 1, NULL);
MonoDC.SelectObject(&MonoDCbmp);
MonoDC.BitBlt(0, 0, w, h, pFromDC, 0, 0, SRCCOPY);
if (m_DrawFlags & PJAI_GRAYSCALE)
{ // convert the image to grayscale. We do this here just
// in case the bitmap has a grayscale colour as the
// transparent colour
Gray = GrayScale(pFromDC, *pFromDC->GetCurrentBitmap());
pFromDC->SelectObject(Gray);
}
// draw the transparent bitmap
pToDC->BitBlt(0, 0, w, h, pFromDC, 0, 0, SRCINVERT);
pToDC->BitBlt(0, 0, w, h, &MonoDC, 0, 0, SRCAND);
pToDC->BitBlt(0, 0, w, h, pFromDC, 0, 0, SRCINVERT);
MonoDC.RestoreDC(savedMonoDC);
pFromDC->RestoreDC(savedFromDC);
pToDC->RestoreDC(savedToDC);
MonoDC.DeleteDC();
if (Gray)
::DeleteObject(Gray);
}
/////////////////////////////////////////////////////////////////////////////
//
// CPJAImage::GetSize (public member function)
// Gets the size of the image in pixels
//
// Parameters :
// None
//
// Returns :
// a CSize containing the size of the image
//
/////////////////////////////////////////////////////////////////////////////
CSize CPJAImage::GetSize()
{
return m_size;
}
/////////////////////////////////////////////////////////////////////////////
//
// CPJAImage::Gray (protected member function)
// Gets the grayscale value of the given colour
//
// Parameters :
// r [in] - the red colour
// g [in] - the green colour
// b [in] - the blue colour
//
// Returns :
// the grayscale value
//
/////////////////////////////////////////////////////////////////////////////
int CPJAImage::Gray(int r, int g, int b)
{
return (b * 11 + g * 59 + r * 30) / 100;
}
/////////////////////////////////////////////////////////////////////////////
//
// CPJAImage::GrayScale (protected member function)
// Creates a DIBSection that is the grayscale equivalant of the given bitmap
//
// Parameters :
// pDC [in] - a pointer to a DC used to build the colour table
// hBitmap [in] - the bitmap to turn grayscale
//
// Returns :
// the HBITMAP of the new grayscale DIBSection
//
// Note :
// when you are finished with the HBITMAP returned by this function
// you have to delete it with a call to ::DeleteObject()
//
// This function does not change the transparent colour to grayscale.
//
/////////////////////////////////////////////////////////////////////////////
HBITMAP CPJAImage::GrayScale(CDC *pDC, HBITMAP hBitmap)
{
// get the bitmap's size and colour information
BITMAP bm;
::GetObject(hBitmap, sizeof(BITMAP), &bm);
// create a DIBSection copy of the original bitmap
HBITMAP hDib = (HBITMAP)::CopyImage(hBitmap, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG | LR_CREATEDIBSECTION);
if (bm.bmBitsPixel < 16)
{ // bitmap has a colour table, so we modify the colour table
CDC memDC;
memDC.CreateCompatibleDC(pDC);
int SavedMemDC = memDC.SaveDC();
memDC.SelectObject(hDib);
int nColours = 1 << bm.bmBitsPixel;
RGBQUAD pal[256];
// Get the colour table
::GetDIBColorTable(memDC.m_hDC, 0, nColours, pal);
// modify the colour table
for (int x = 0; x < nColours; x++)
{
if (!IsTransparent(pal[x].rgbRed, pal[x].rgbGreen, pal[x].rgbBlue))
{
BYTE nGray = (BYTE)Gray(pal[x].rgbRed, pal[x].rgbGreen, pal[x].rgbBlue);
pal[x].rgbRed = nGray;
pal[x].rgbGreen = nGray;
pal[x].rgbBlue = nGray;
}
}
// set the modified colour tab to the DIBSection bitmap
::SetDIBColorTable(memDC.m_hDC, 0, nColours, pal);
memDC.RestoreDC(SavedMemDC);
memDC.DeleteDC();
return hDib;
}
else
{ // the bitmap does not have a colour table, so we modify the bitmap bits directly
int Size = bm.bmHeight * bm.bmWidth;
BITMAPINFO bmi;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biHeight = bm.bmHeight;
bmi.bmiHeader.biWidth = bm.bmWidth;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = bm.bmBitsPixel;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = ((bm.bmWidth * bm.bmBitsPixel + 31) & (~31)) / 8 * bm.bmHeight;
bmi.bmiHeader.biXPelsPerMeter = 0;
bmi.bmiHeader.biYPelsPerMeter = 0;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
// Get the bitmaps data bits
BYTE *pBits = new BYTE[bmi.bmiHeader.biSizeImage];
VERIFY (::GetDIBits(pDC->m_hDC, hDib, 0, bm.bmHeight, pBits, &bmi, DIB_RGB_COLORS));
if (bm.bmBitsPixel == 32)
{
DWORD *dst=(DWORD *)pBits;
while (Size--)
{
if (!IsTransparent(GetBValue(*dst), GetGValue(*dst), GetRValue(*dst)))
{
int nGray = Gray(GetBValue(*dst), GetGValue(*dst), GetRValue(*dst));
*dst = (DWORD)RGB(nGray, nGray, nGray);
}
dst++;
}
}
else if (bm.bmBitsPixel == 24)
{
BYTE *dst=(BYTE*)pBits;
for (int dh = 0; dh < bm.bmHeight; dh++)
{
for (int dw = 0; dw < bm.bmWidth; dw++)
{
if (!IsTransparent(dst[2], dst[1], dst[0]))
{
int nGray = Gray(dst[2], dst[1], dst[0]);
dst[0]=(BYTE)nGray;
dst[1]=(BYTE)nGray;
dst[2]=(BYTE)nGray;
}
dst += 3;
}
// each row is DWORD aligned, so when we reach the end of a row, we
// have to realign the pointer to point to the start of the next row
int pos = (int)dst - (int)pBits;
int rem = pos % 4;
if (rem)
dst += 4 - rem;
}
}
else if (bm.bmBitsPixel == 16)
{
WORD *dst=(WORD*)pBits;
while (Size--)
{
BYTE b = (BYTE)((*dst)&(0x1F));
BYTE g = (BYTE)(((*dst)>>5)&(0x1F));
BYTE r = (BYTE)(((*dst)>>10)&(0x1F));
if (!IsTransparent(r, g, b))
{
int nGray = Gray(r, g, b);
*dst = ((WORD)(((BYTE)(nGray)|((WORD)((BYTE)(nGray))<<5))|(((DWORD)(BYTE)(nGray))<<10)));
}
dst++;
}
}
// set the modified bitmap data bits to the DIBSection
::SetDIBits(pDC->m_hDC, hDib, 0, bm.bmHeight, pBits, &bmi, DIB_RGB_COLORS);
delete[] pBits;
return hDib;
}
}
/////////////////////////////////////////////////////////////////////////////
//
// CPJAImage::IsTransparent (protected member function)
// checks if the given colour values make up the transparent colour for the bitmap
//
// Parameters :
// r [in] - the red colour
// g [in] - the green colour
// b [in] - the blue colour
//
// Returns :
// TRUE if the colour is the transparent colour
// FALSE if not
//
/////////////////////////////////////////////////////////////////////////////
BOOL CPJAImage::IsTransparent(int r, int g, int b)
{
if (!(m_DrawFlags & PJAI_TRANSPARENT))
return FALSE;
return (RGB(r, g, b) == m_TransparentColour);
}
/////////////////////////////////////////////////////////////////////////////
//
// CPJAImage::SetImage (public member function)
// Sets the image and image flags
//
// Parameters :
// Image [in] - a HANDLE of the image to set (either a HBITMAP or a HICON)
// Flags [in] - the flags that specify the type of image and how it is drawn
//
// Returns :
// TRUE on success
// FALSE on failure
//
// Note :
// See the PJAImage.h file for a description of the flags used
//
/////////////////////////////////////////////////////////////////////////////
BOOL CPJAImage::SetImage(HANDLE Image, DWORD Flags)
{
if (Image)
{ // verify flags
if (!((Flags & PJAI_BITMAP ? 1 : 0) ^ (Flags & PJAI_ICON ? 1 : 0)))
{
TRACE (_T("PJAI_Image::SetImage() : Must specify either PJAI_BITMAP or PJAI_ICON"));
ASSERT (FALSE);
return FALSE;
}
}
if (m_hImage && m_hImage != Image)
{
if (m_ImageFlags & PJAI_AUTODELETE)
{ // remove the old image
if (m_ImageFlags & PJAI_ICON)
DestroyIcon((HICON)m_hImage);
else
DeleteObject((HGDIOBJ)m_hImage);
}
m_hImage = NULL;
m_size.cx = 0;
m_size.cy = 0;
m_TransparentColour = CLR_DEFAULT;
}
if (Image)
{ // get the image dimensions
if (Flags & PJAI_BITMAP)
{
BITMAP bmp;
if (GetObject((HBITMAP)Image, sizeof(BITMAP), &bmp))
{
m_size.cx = bmp.bmWidth;
m_size.cy = bmp.bmHeight;
}
}
else if (Flags & PJAI_ICON)
{
ICONINFO iconinfo;
GetIconInfo((HICON)Image, &iconinfo);
BITMAP bmp;
if (GetObject(iconinfo.hbmMask, sizeof(BITMAP), &bmp))
{
m_size.cx = bmp.bmWidth;
m_size.cy = iconinfo.hbmColor ? bmp.bmHeight : bmp.bmHeight / 2;
}
// prevent a resource leak
DeleteObject(iconinfo.hbmColor);
DeleteObject(iconinfo.hbmMask);
}
}
m_hImage = Image;
m_ImageFlags = Flags;
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// CPJAImage::SetTransparentColour (public member function)
// Set the colour to be used as the transparent colour
//
// Parameters :
// clr [in] - the colour to be used as the transparent colour
//
// Returns :
// the old transparent colour
//
// Note :
// If the colour is CLR_DEFAULT (the default), the colour of the
// top left pixel (0,0) is used as the transparent colour.
//
/////////////////////////////////////////////////////////////////////////////
COLORREF CPJAImage::SetTransparentColour(COLORREF clr /*= CLR_DEFAULT*/)
{
COLORREF oldclr = m_TransparentColour;
m_TransparentColour = clr;
return oldclr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -