zoukankan      html  css  js  c++  java
  • 一个图片加载与绘制类(使用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;
    }
  • 相关阅读:
    Verilog非阻塞赋值的仿真/综合问题 (Nonblocking Assignments in Verilog Synthesis)上
    异步FIFO结构及FPGA设计 跨时钟域设计
    FPGA管脚分配需要考虑的因素
    An Introduction to Delta Sigma Converters (DeltaSigma转换器 上篇)
    An Introduction to Delta Sigma Converters (DeltaSigma转换器 下篇)
    中国通信简史 (下)
    谈谈德国大学的电子专业
    中国通信简史 (上)
    Verilog学习笔记
    Verilog非阻塞赋值的仿真/综合问题(Nonblocking Assignments in Verilog Synthesis) 下
  • 原文地址:https://www.cnblogs.com/lzjsky/p/1795667.html
Copyright © 2011-2022 走看看