• 一个图片加载与绘制类(使用GDI输出图片)【补充】


    《一个图片加载与绘制类(使用GDI输出图片)》中我公布了基本的图片加载和绘制类,我们可以再根据这个类派生一些我们需要的新的绘制类,来针对某些特殊情况的绘制和使用,下面我再公布一个这样的类,作为样例。其中部分代码来源于互联网。

    一、头文件(CImageLoader.h)

    #include "EnBitmap.h"

    class CImageLoader : public CEnBitmap  
    {
    public:
        BOOL DrawImage(CEnBitmap
    & bmp, int nX, int nY, int nCol, int nRow);
        CImageLoader();
        
    virtual ~CImageLoader();

        BOOL Draw( CDC 
    *pDC, LPRECT r);
        
    //draw sub bmp to special point
        BOOL Draw( CDC *pDC, int x, int y, LPRECT sr );
        BOOL Draw( CDC 
    *pDC, int x, int y, LPRECT sr, COLORREF colTrans, BOOL bTrans );
        BOOL DrawByHeight(CDC
    * pDC, int x, int y, int sx, int sy, LPRECT sr, int nHeight);
        
        
    int     Width()return GetWidth(); }
        
    int     Height()return GetHeight(); }
        
        
    void Attach(HBITMAP hbmp) { CBitmap::Attach(hbmp); }
        
        BOOL LoadBitmap(UINT nResName, HMODULE hInst
    =NULL, COLORREF crBack=0
        

            
    if(m_hBitmap) DeleteObject();
            
    return LoadImage(nResName,RT_BITMAP,hInst,crBack);
        }

        BOOL LoadBitmap(LPCTSTR lpctImagePath, COLORREF crBack
    =0
        

            
    if(m_hBitmap) DeleteObject();
            
    return LoadImage(lpctImagePath,crBack);
        }

        
        BOOL DrawTransparent(CDC 
    * pDC, int x, int y, COLORREF crColour);    
        HRGN CreateRgnFromFile( COLORREF color );

        BOOL DrawImageByIndex(CDC
    * pDC, CRect rect, int nIndex, COLORREF clrTrans, BOOL bTrans);
    }
    ;


    二、源文件(CImageLoader.cpp)

    #include "stdafx.h"
    #include 
    "GnetImageLoader.h"

    //////////////////////////////////////////////////////////////////////
    // Construction/Destruction
    //////////////////////////////////////////////////////////////////////

    CImageLoader::CImageLoader()
    {

    }


    CImageLoader::
    ~CImageLoader()
    {

    }


    BOOL CImageLoader::Draw( CDC 
    *pDC, int x, int y, LPRECT sr, COLORREF colTrans, BOOL bTrans )
    {
        
    if ( !bTrans )
            Draw( pDC ,x, y, sr );
        
    else
        
    {
            MyTransparentBlt( pDC
    ->m_hDC, x, y, sr->right - sr->left, sr->bottom - sr->top, 
                m_hBitmap, sr
    ->left, sr->top, colTrans, NULL );
        }

        
    return TRUE;
    }


    //draw sub bmp to special point
    BOOL CImageLoader::Draw( CDC *pDC, int x, int y, LPRECT sr )
    {
        CDC dc;
        dc.CreateCompatibleDC( pDC
    ->m_hDC );
        HBITMAP bmp 
    = dc.SelectBitmap( m_hBitmap );    
        
    if ( sr != NULL)
            pDC
    ->BitBlt( x, y, sr->right - sr->left, sr->bottom - sr->top, dc.m_hDC, 
                sr
    ->left, sr->top,  SRCCOPY );
        
    else
            pDC
    ->BitBlt( x, y, Width(), Height(), dc.m_hDC, 
                
    00,  SRCCOPY );
        dc.SelectBitmap( bmp );
        
        
    if(dc.m_hDC) ::DeleteDC(dc.Detach());
        
        
    return TRUE;
    }


    BOOL CImageLoader::DrawByHeight(CDC
    * pDC, int x, int y, int sx, int sy, LPRECT sr, int nHeight)
    {
        CDC dc;
        dc.CreateCompatibleDC(pDC
    ->m_hDC);
        HBITMAP hBitmap 
    = dc.SelectBitmap(m_hBitmap);

        
    if(sr == NULL)
            pDC
    ->BitBlt(x, y, Width(), Height(), dc.m_hDC, 00, SRCCOPY);
        
    else
        
    {
            
    int nSrcWidth = sr->right - sr->left;
            
    int nSrcHeight = sr->bottom - sr->top;

            
    if(nSrcHeight == nHeight)
                pDC
    ->BitBlt(x, y, nSrcWidth, nSrcHeight, dc.m_hDC, sr->left, sr->top, SRCCOPY);
            
    else
            
    {
                
    //高度不同,需要拉伸绘制(根据指定的高度值:nHeight)
                pDC->StretchBlt(x, y, sr->right-sr->left, nHeight, dc.m_hDC, sx, sy, nSrcWidth, nSrcHeight, SRCCOPY);
            }

        }


        dc.SelectBitmap(hBitmap);
        ::DeleteDC(dc.Detach());

        
    return TRUE;
    }


    BOOL CImageLoader::Draw(CDC 
    *pDC, LPRECT r)
    {
        CDC dc;
        dc.CreateCompatibleDC( pDC
    ->m_hDC );
        HBITMAP bmp 
    = dc.SelectBitmap( m_hBitmap );    
        pDC
    ->BitBlt( r->left, r->top, r->right - r->left, r->bottom - r->top, dc.m_hDC, 00 ,
              SRCCOPY );

        dc.SelectBitmap( bmp );

        
    if(dc.m_hDC) ::DeleteDC(dc.Detach());
        
        
    return TRUE;
    }



    ///HOWTO: Drawing Transparent Bitmaps
    //see: Microsoft Knowledge Base Article - Q79212
    BOOL CImageLoader::DrawTransparent(CDC * pDC, int x, int y, COLORREF crColour)
    {
        MyTransparentBlt( pDC
    ->m_hDC, x, y, GetWidth(), GetHeight(), m_hBitmap, 00, crColour, NULL );

        
    return TRUE;
    }
        


    HRGN CImageLoader::CreateRgnFromFile( COLORREF color )
    {
        HBITMAP hBmp 
    = m_hBitmap;

        
    // get image properties
        BITMAP bmp = 0 };
        ::GetObject( hBmp, 
    sizeof(BITMAP), &bmp );
        
    // allocate memory for extended image information
        LPBITMAPINFO bi = (LPBITMAPINFO) new BYTE[ sizeof(BITMAPINFO) + 8 ];
        memset( bi, 
    0sizeof(BITMAPINFO) + 8 );
        bi
    ->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        
    // set window size
        int m_dwWidth    = bmp.bmWidth;        // bitmap width
        int m_dwHeight    = bmp.bmHeight;        // bitmap height
        
    // create temporary dc
        HDC dc = CreateIC( "DISPLAY",NULL,NULL,NULL );
        
    // get extended information about image (length, compression, length of color table if exist, ...)
        DWORD res = ::GetDIBits( dc, hBmp, 0, bmp.bmHeight, 0, bi, DIB_RGB_COLORS );
        
    // allocate memory for image data (colors)
        LPBYTE pBits = new BYTE[ bi->bmiHeader.biSizeImage + 4 ];
        
    // allocate memory for color table
        if ( bi->bmiHeader.biBitCount == 8 )
        
    {
            
    // actually color table should be appended to this header(BITMAPINFO),
            
    // so we have to reallocate and copy it
            LPBITMAPINFO old_bi = bi;
            
    // 255 - because there is one in BITMAPINFOHEADER
            bi = (LPBITMAPINFO)new charsizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD) ];
            memcpy( bi, old_bi, 
    sizeof(BITMAPINFO) );
            
    // release old header
            delete old_bi;
        }

        
    // get bitmap info header
        BITMAPINFOHEADER& bih = bi->bmiHeader;
        
    // get color table (for 256 color mode contains 256 entries of RGBQUAD(=DWORD))
        LPDWORD clr_tbl = (LPDWORD)&bi->bmiColors;
        
    // fill bits buffer
        res = ::GetDIBits( dc, hBmp, 0, bih.biHeight, pBits, bi, DIB_RGB_COLORS );
        DeleteDC( dc );

        BITMAP bm;
        ::GetObject( hBmp, 
    sizeof(BITMAP), &bm );
        
    // shift bits and byte per pixel (for comparing colors)
        LPBYTE pClr = (LPBYTE)&color;
        
    // swap red and blue components
        BYTE tmp = pClr[0]; pClr[0= pClr[2]; pClr[2= tmp;
        
    // convert color if curent DC is 16-bit (5:6:5) or 15-bit (5:5:5)
        if ( bih.biBitCount == 16 )
        
    {
            
    // for 16 bit
            color = ((DWORD)(pClr[0& 0xf8>> 3|
                    ((DWORD)(pClr[
    1& 0xfc<< 3|
                    ((DWORD)(pClr[
    2& 0xf8<< 8);
            
    // for 15 bit
    //        color = ((DWORD)(pClr[0] & 0xf8) >> 3) |
    //                ((DWORD)(pClr[1] & 0xf8) << 2) |
    //                ((DWORD)(pClr[2] & 0xf8) << 7);
        }


        
    const DWORD RGNDATAHEADER_SIZE    = sizeof(RGNDATAHEADER);
        
    const DWORD ADD_RECTS_COUNT        = 40;            // number of rects to be appended
                                                        
    // to region data buffer

        
    // BitPerPixel
        BYTE    Bpp = bih.biBitCount >> 3;                // bytes per pixel
        
    // bytes per line in pBits is DWORD aligned and bmp.bmWidthBytes is WORD aligned
        
    // so, both of them not
        DWORD m_dwAlignedWidthBytes = (bmp.bmWidthBytes & ~0x3+ (!!(bmp.bmWidthBytes & 0x3<< 2);
        
    // DIB image is flipped that's why we scan it from the last line
        LPBYTE    pColor = pBits + (bih.biHeight - 1* m_dwAlignedWidthBytes;
        DWORD    dwLineBackLen 
    = m_dwAlignedWidthBytes + bih.biWidth * Bpp;    // offset of previous scan line
                                                        
    // (after processing of current)
        DWORD    dwRectsCount = bih.biHeight;            // number of rects in allocated buffer
        INT        i, j;                                    // current position in mask image
        INT        first = 0;                                // left position of current scan line
                                                        
    // where mask was found
        bool    wasfirst = false;                        // set when mask has been found in current scan line
        bool    ismask;                                    // set when current color is mask color

        
    // allocate memory for region data
        
    // region data here is set of regions that are rectangles with height 1 pixel (scan line)
        
    // that's why first allocation is <bm.biHeight> RECTs - number of scan lines in image
        RGNDATAHEADER* pRgnData = 
            (RGNDATAHEADER
    *)new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
        
    // get pointer to RECT table
        LPRECT pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
        
    // zero region data header memory (header  part only)
        memset( pRgnData, 0, RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) );
        
    // fill it by default
        pRgnData->dwSize    = RGNDATAHEADER_SIZE;
        pRgnData
    ->iType        = RDH_RECTANGLES;

        
    for ( i = 0; i < bih.biHeight; i++ )
        
    {
            
    for ( j = 0; j < bih.biWidth; j++ )
            
    {
                
    // get color
                switch ( bih.biBitCount )
                
    {
                
    case 8:
                    ismask 
    = (clr_tbl[ *pColor ] != color);
                    
    break;
                
    case 16:
                    ismask 
    = (*(LPWORD)pColor != (WORD)color);
                    
    break;
                
    case 24:
                    ismask 
    = ((*(LPDWORD)pColor & 0x00ffffff!= color);
                    
    break;
                
    case 32:
                    ismask 
    = (*(LPDWORD)pColor != color);
                }

                
    // shift pointer to next color
                pColor += Bpp;
                
    // place part of scan line as RECT region if transparent color found after mask color or
                
    // mask color found at the end of mask image
                if ( wasfirst )
                
    {
                    
    if ( !ismask )
                    
    {
                        
    // save current RECT
                        pRects[ pRgnData->nCount++ ] = CRect( first, i, j, i + 1 );
                        
    // if buffer full reallocate it with more room
                        if ( pRgnData->nCount >= dwRectsCount )
                        
    {
                            dwRectsCount 
    += ADD_RECTS_COUNT;
                            
    // allocate new buffer
                            LPBYTE pRgnDataNew = new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
                            
    // copy current region data to it
                            memcpy( pRgnDataNew, pRgnData, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT) );
                            
    // delte old region data buffer
                            delete pRgnData;
                            
    // set pointer to new regiondata buffer to current
                            pRgnData = (RGNDATAHEADER*)pRgnDataNew;
                            
    // correct pointer to RECT table
                            pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
                        }

                        wasfirst 
    = false;
                    }

                }

                
    else if ( ismask )        // set wasfirst when mask is found
                {
                    first 
    = j;
                    wasfirst 
    = true;
                }

            }


            
    if ( wasfirst && ismask )
            
    {
                
    // save current RECT
                pRects[ pRgnData->nCount++ ] = CRect( first, i, j, i + 1 );
                
    // if buffer full reallocate it with more room
                if ( pRgnData->nCount >= dwRectsCount )
                
    {
                    dwRectsCount 
    += ADD_RECTS_COUNT;
                    
    // allocate new buffer
                    LPBYTE pRgnDataNew = new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ];
                    
    // copy current region data to it
                    memcpy( pRgnDataNew, pRgnData, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT) );
                    
    // delte old region data buffer
                    delete pRgnData;
                    
    // set pointer to new regiondata buffer to current
                    pRgnData = (RGNDATAHEADER*)pRgnDataNew;
                    
    // correct pointer to RECT table
                    pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE);
                }

                wasfirst 
    = false;
            }


            pColor 
    -= dwLineBackLen;
        }

        
    // release image data
        delete pBits;
        delete bi;

        
    // create region
        HRGN hRgn = ExtCreateRegion( NULL, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT), (LPRGNDATA)pRgnData );
        
    // release region data
        delete pRgnData;

        
    return hRgn;
    }


    BOOL CImageLoader::DrawImage(CEnBitmap 
    &bmp, int nX, int nY, int nCol, int nRow)
    {
        nX 
    -= 1;
        nY 
    -= 1;
        
    int w = GetWidth()/nCol;
        
    int h = GetHeight()/nRow;
        
        HBITMAP hOldBmp;
        CDC memDC;
        CClientDC dc(
    0);
        
        memDC.CreateCompatibleDC(dc.m_hDC);
        bmp.CreateCompatibleBitmap(dc.m_hDC, w, h);
        
        hOldBmp 
    = memDC.SelectBitmap(bmp.m_hBitmap);
        StretchDraw( 
    &memDC, CRect( 00, w, h ),
            CRect(GetWidth()
    *nX/nCol, GetHeight()*nY/nRow, GetWidth()*nX/nCol+w ,GetHeight()*nY/nRow+h ) );
        memDC.SelectBitmap(hOldBmp);
        
        
    //dc.DeleteDC();
        memDC.DeleteDC();
        ::DeleteObject(hOldBmp);
        hOldBmp 
    = NULL;
        
        
    return TRUE;
    }


    //////////////////////////////////////////////////////////////////////////
    ///
    ///    @param [in] pDC    Device context
    ///    @param [in] x    
    ///    @param [in] y
    ///    @param [in] rect
    ///    @param [in] state    Button state
    ///    - 0 : Normal
    ///    - 1 : Pressed
    ///    - 2 : Hover
    ///    - 3 : Disabled
    ///    @param [in] clrTrans
    ///    @param [in] bTrans                    
    ///
    //////////////////////////////////////////////////////////////////////////

    BOOL CImageLoader::DrawImageByIndex(CDC* pDC, CRect rect, int nIndex, COLORREF clrTrans, BOOL bTrans)
    {
        
    if(m_hBitmap == NULL) return FALSE;
        
        Draw(pDC, rect.left, rect.top, CRect(nIndex
    *rect.Width(), 0, (nIndex+1)*rect.Width(), GetHeight()), clrTrans, bTrans);
        
        
    return TRUE;
    }
  • 相关阅读:
    C结构体之位域(位段)
    Linux 有效用户组(effective group)与初始用户组(initial group)(参考鸟哥私房菜)
    牛顿迭代法求平方根
    操作系统 第5章 哲学家问题
    面试题3:数组中重复的数字
    某讯实习生后台开发一面总结
    面试题目4:二维数组中的查找
    Java基础知识之基本概念
    Maven常用命令
    Maven仓库
  • 原文地址:https://www.cnblogs.com/lzjsky/p/1795667.html
Copyright © 2020-2023  润新知