zoukankan      html  css  js  c++  java
  • 使用StretchBlt之前一定要用SetStretchBltMode(COLORONCOLOR)

    近日要实现将缩小的位图保存在后台,以便在OnPaint刷新的时候仍然可以看到正确的图像,遂在lg_Bitmap类中添加了这样一个函数

        BOOL lg_Bitmap::LoadFromHDC(HDC hDC)
        
    {
            
    if(NULL == hDC)
                
    return FALSE;
            BITMAP Bitmap;
            HBITMAP hBitmap 
    = (HBITMAP)::GetCurrentObject(hDC,OBJ_BITMAP);
            
            ::GetObject(hBitmap,
    sizeof(BITMAP),&Bitmap); 

            
    if(Bitmap.bmHeight <= 0||Bitmap.bmWidth <= 0||Bitmap.bmWidthBytes <= 0)
                
    return FALSE;

            BITMAPINFOHEADER
    & bih = m_bmi.bmiHeader;
            ::ZeroMemory( 
    &bih, sizeof( BITMAPINFOHEADER ));
            bih.biSize        
    = sizeof( BITMAPINFOHEADER );
            bih.biWidth       
    = Bitmap.bmWidth;
            bih.biHeight      
    = Bitmap.bmHeight;
            bih.biCompression 
    = BI_RGB;//BI_JPEG;//BI_JPEG
            bih.biPlanes      = 1;
            bih.biBitCount      
    = 24;
            
            
    int nLineDataSize = ((bih.biBitCount * Bitmap.bmWidth+31)/32)*4;
            bih.biWidth       
    = nLineDataSize/(bih.biBitCount/8);//(width * nChannels * 8 +31) / 8;
            int nLineCopySize = bih.biWidth*(bih.biBitCount/8);
            DWORD dwWholeSize 
    = nLineDataSize * abs(bih.biHeight);
            BYTE
    * pTemp = new BYTE[dwWholeSize];
            memset(pTemp,
    0,dwWholeSize);

            
    int nLine = ::GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
                pTemp,
    &m_bmi, DIB_RGB_COLORS);

            
    if(nLine <= 0)
            
    {
                delete [] pTemp;
                
    return FALSE;
            }

            BOOL bSuccess
    =CreateBitmapIndirect(&m_bmi, pTemp);
            delete [] pTemp;
            
    return bSuccess;
        }

    然后在外部如此调用

            CDC * pScreenDC = new CDC;
            pScreenDC
    ->CreateCompatibleDC(pDC);
            CBitmap TempBitmap;
            TempBitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
            CBitmap
    * pOldScreenDC = NULL;
            pOldScreenDC 
    = (CBitmap*)pScreenDC->SelectObject(&TempBitmap);
            pScreenDC->StretchBlt(0,0,rect.Width(),rect.Height(),pMemDC,0,0,BIT.bmWidth,BIT.bmHeight,SRCCOPY);
            DrawTxtInDC(pScreenDC,
    5,15,topinfo,strPosition,rect.Height());
            
    if(g_ScreenBitmap.LoadFromHDC(pScreenDC->GetSafeHdc()))
            
    {
                m_bHaveDataInBuffer 
    = TRUE;
            }
    else{
                m_bHaveDataInBuffer 
    = FALSE;
            }

            pScreenDC
    ->SelectObject(pOldScreenDC);
            delete pScreenDC;

    再然后界面显示了一张这样的图

    我就郁闷了,好好的图咋整这样了呢?开始找原因
    由于位图类中没有提供保存位图的功能,遂再增加两个函数
    1,保存lg_Bitmap自身的图 2,保存指定LPBITMAPINFOHEADER,和缓冲的图

        //不支持调色板
        BOOL lg_Bitmap::SaveThis(LPCTSTR fn)
        
    {
            BITMAP bmp;
            GetBitmap(
    &bmp);
            
    return Save(&m_bmi.bmiHeader,bmp.bmBits,fn);
        }

        BOOL lg_Bitmap::Save(LPBITMAPINFOHEADER lpIn,LPVOID lpBuf,LPCTSTR fn)
        
    {
            
    //位图文件大小 , 写入文件字节数
            DWORD dwBmBitsSize,dwDIBSize;

            
    //位图文件头结构
            BITMAPFILEHEADER   bmfHdr;    
        
            
    //指向位图信息头结构
            LPBITMAPINFOHEADER lpbi;

            dwBmBitsSize 
    = ((lpIn->biWidth *lpIn->biBitCount+31)/32)* 4*lpIn->biHeight;

            
    //为位图内容分配内存
            HANDLE hDib  = GlobalAlloc(GHND,dwBmBitsSize+sizeof(BITMAPINFOHEADER));
            lpbi 
    = (LPBITMAPINFOHEADER)GlobalLock(hDib);
            memcpy(lpbi,lpIn,
    sizeof(BITMAPINFOHEADER));

            memcpy((LPSTR)lpbi 
    + sizeof(BITMAPINFOHEADER),lpBuf,dwBmBitsSize);

            
    // 设置位图文件头
            bmfHdr.bfType = 0x4D42;  // "BM"
            dwDIBSize    = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmBitsSize;  
            bmfHdr.bfSize 
    = dwDIBSize;
            bmfHdr.bfReserved1 
    = 0;
            bmfHdr.bfReserved2 
    = 0;
            bmfHdr.bfOffBits 
    = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
            
    if(!SaveDataToFile((LPSTR)&bmfHdr,sizeof(BITMAPFILEHEADER),fn,TRUE))
            
    {
                GlobalUnlock(hDib);
                GlobalFree(hDib);
                
    return FALSE;
            }

            
    if(!SaveDataToFile((LPSTR)lpbi,dwDIBSize,fn))
            
    {
                GlobalUnlock(hDib);
                GlobalFree(hDib);
                
    return FALSE;
            }


            GlobalUnlock(hDib);
            GlobalFree(hDib);
            
    return TRUE;
        }

    然后在lg_Bitmap::LoadFromHDC(HDC hDC)的结尾加入这么一段

            lg_TimeString Tsing;
            
    string sPath = Tsing.Format("e:\抓图\%N%Y%R%S%F%M%H.bmp");
            CreateAllDirectory(sPath.c_str());
    //        SaveThis(sPath.c_str());
            Save(&bih,pTemp,sPath.c_str());

    结果无论是lg_Bitmap自身还是外部传来的位图无一例外的变成了上面那个图的样子
    ..............思考中,无意中在google上看到一句话,在使用StretchBlt缩小位图的时候要SetStretchBltMode(COLORONCOLOR).......我晕,管他先试试。

            CDC * pScreenDC = new CDC;
            pScreenDC
    ->CreateCompatibleDC(pDC);
            CBitmap TempBitmap;
            TempBitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
            CBitmap
    * pOldScreenDC = NULL;
            pOldScreenDC 
    = (CBitmap*)pScreenDC->SelectObject(&TempBitmap);
            pScreenDC
    ->SetStretchBltMode(COLORONCOLOR);
            pScreenDC
    ->StretchBlt(0,0,rect.Width(),rect.Height(),pMemDC,0,0,BIT.bmWidth,BIT.bmHeight,SRCCOPY);
            DrawTxtInDC(pScreenDC,
    5,15,topinfo,strPosition,rect.Height());
            
    if(g_ScreenBitmap.LoadFromHDC(pScreenDC->GetSafeHdc()))
            
    {
                m_bHaveDataInBuffer 
    = TRUE;
            }
    else{
                m_bHaveDataInBuffer 
    = FALSE;
            }

            pScreenDC
    ->SelectObject(pOldScreenDC);
            delete pScreenDC;

    结果

  • 相关阅读:
    Add Two Numbers
    Reverse Linked List II
    Reverse Linked List
    Remove Duplicates from Sorted List
    Remove Duplicates from Sorted List II
    Partition List
    Intersection of Two Linked Lists
    4Sum
    3Sum
    2Sum
  • 原文地址:https://www.cnblogs.com/buffer/p/1434219.html
Copyright © 2011-2022 走看看