⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pjaimage.cpp

📁 MiniCA V2.0版本源码。《小型CA系统V2.1含源码》发表以来
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//  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 + -