• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • BMP位圖文件結構及平滑縮放

    發表于:2007-07-14來源:作者:點擊數: 標簽:
    西安交通大學流體機械研究所 張義云 用普通方法顯示BMP位圖,占內存大,速度慢,在圖形縮小時,失真嚴重,在低顏色位數的設備上顯示高顏色位數的圖形圖形時失真大。本文采用視頻函數顯示BMP位圖,可以消除以上的缺點。 一、BMP文件結構 BMP文件組成 BMP文件由
    西安交通大學流體機械研究所
    張義云

      用普通方法顯示BMP位圖,占內存大,速度慢,在圖形縮小時,失真嚴重,在低顏色位數的設備上顯示高顏色位數的圖形圖形時失真大。本文采用視頻函數顯示BMP位圖,可以消除以上的缺點。

    一、BMP文件結構

    BMP文件組成
    BMP文件由文件頭、位圖信息頭、顏色信息和圖形數據四部分組成。
    BMP文件頭
    BMP文件頭數據結構含有BMP文件的類型、文件大小和位圖起始位置等信息。
    其結構定義如下:
    typedef struct tagBITMAPFILEHEADER
    {
    WORDbfType; // 位圖文件的類型,必須為BM
    DWORD bfSize; // 位圖文件的大小,以字節為單位
    WORDbfReserved1; // 位圖文件保留字,必須為0
    WORDbfReserved2; // 位圖文件保留字,必須為0
    DWORD bfOffBits; // 位圖數據的起始位置,以相對于位圖
    // 文件頭的偏移量表示,以字節為單位
    } BITMAPFILEHEADER;


    3. 位圖信息頭


    BMP位圖信息頭數據用于說明位圖的尺寸等信息。
    typedef struct tagBITMAPINFOHEADER{
    DWORD biSize; // 本結構所占用字節數
    LONGbiWidth; // 位圖的寬度,以像素為單位
    LONGbiHeight; // 位圖的高度,以像素為單位
    WORD biPlanes; // 目標設備的級別,必須為1
    WORD biBitCount// 每個像素所需的位數,必須是1(雙色),
    // 4(16色),8(256色)或24(真彩色)之一
    DWORD biCompression; // 位圖壓縮類型,必須是 0(不壓縮),
    // 1(BI_RLE8壓縮類型)或2(BI_RLE4壓縮類型)之一
    DWORD biSizeImage; // 位圖的大小,以字節為單位
    LONGbiXPelsPerMeter; // 位圖水平分辨率,每米像素數
    LONGbiYPelsPerMeter; // 位圖垂直分辨率,每米像素數
    DWORD biClrUsed;// 位圖實際使用的顏色表中的顏色數
    DWORD biClrImportant;// 位圖顯示過程中重要的顏色數
    } BITMAPINFOHEADER;


    4. 顏色表

      顏色表用于說明位圖中的顏色,它有若干個表項,每一個表項是一個RGBQUAD類型的結構,定義一種顏色。RGBQUAD結構的定義如下:
    typedef struct tagRGBQUAD {
    BYTErgbBlue;// 藍色的亮度(值范圍為0-255)
    BYTErgbGreen; // 綠色的亮度(值范圍為0-255)
    BYTErgbRed; // 紅色的亮度(值范圍為0-255)
    BYTErgbReserved;// 保留,必須為0
    } RGBQUAD;
    顏色表中RGBQUAD結構數據的個數有biBitCount來確定:
    當biBitCount=1,4,8時,分別有2,16,256個表項;
    當biBitCount=24時,沒有顏色表項。
    位圖信息頭和顏色表組成位圖信息,BITMAPINFO結構定義如下:
    typedef struct tagBITMAPINFO {
    BITMAPINFOHEADER bmiHeader; // 位圖信息頭
    RGBQUAD bmiColors[1]; // 顏色表
    } BITMAPINFO;


    5. 位圖數據
      位圖數據記錄了位圖的每一個像素值,記錄順序是在掃描行內是從左到右,掃描行之間是從下到上。位圖的一個像素值所占的字節數:
    當biBitCount=1時,8個像素占1個字節;
    當biBitCount=4時,2個像素占1個字節;
    當biBitCount=8時,1個像素占1個字節;
    當biBitCount=24時,1個像素占3個字節;
    Windows規定一個掃描行所占的字節數必須是
    4的倍數(即以long為單位),不足的以0填充,
    一個掃描行所占的字節數計算方法:
    DataSizePerLine= (biWidth* biBitCount+31)/8;
    // 一個掃描行所占的字節數
    DataSizePerLine= DataSizePerLine/4*4; // 字節數必須是4的倍數
    位圖數據的大小(不壓縮情況下):
    DataSize= DataSizePerLine* biHeight;


    二、BMP位圖一般顯示方法

    1. 申請內存空間用于存放位圖文件
      GlobalAlloc(GHND,FileLength);

    2. 位圖文件讀入所申請內存空間中
       LoadFileToMemory( mpBitsSrc,mFileName);

    3. 在OnPaint等函數中用創建顯示用位圖
      用CreateDIBitmap()創建顯示用位圖,用CreateCompatibleDC()創建兼容DC,
      用SelectBitmap()選擇顯示位圖。

    4. 用BitBlt或StretchBlt等函數顯示位圖

    5. 用DeleteObject()刪除所創建的位圖

      以上方法的缺點是: 1)顯示速度慢; 2) 內存占用大; 3) 位圖在縮小顯示時圖形失真大,(可通過安裝字體平滑軟件來解決); 4) 在低顏色位數的設備上(如256顯示模式)顯示高顏色位數的圖形(如真彩色)圖形失真嚴重。

    三、BMP位圖縮放顯示
       用DrawDib視頻函數來顯示位圖,內存占用少,速度快,而且還可以對圖形進行淡化(Dithering)處理。淡化處理是一種圖形算法,可以用來在一個支持比圖像所用顏色要少的設備上顯示彩色圖像。BMP位圖顯示方法如下:

    1. 打開視頻函數DrawDibOpen(),一般放在在構造函數中

    2. 申請內存空間用于存放位圖文件
      GlobalAlloc(GHND,FileLength);

    3. 位圖文件讀入所申請內存空間中----
      LoadFileToMemory( mpBitsSrc,mFileName);

    4. 在OnPaint等函數中用DrawDibRealize(),DrawDibDraw()顯示位圖

    5. 關閉視頻函數DrawDibClose(),一般放在在析構函數中

      以上方法的優點是: 1)顯示速度快; 2) 內存占用少; 3) 縮放顯示時圖形失真小,4) 在低顏色位數的設備上顯示高顏色位數的圖形圖形時失真小; 5) 通過直接處理位圖數據,可以制作簡單動畫。

    四、CViewBimap類編程要點

    1. 在CViewBimap類中添加視頻函數等成員

    HDRAWDIB m_hDrawDib; // 視頻函數
    HANDLEmhBitsSrc; // 位圖文件句柄(內存)
    LPSTR mpBitsSrc; // 位圖文件地址(內存)
    BITMAPINFOHEADER *mpBitmapInfo; // 位圖信息頭

    2. 在CViewBimap類構造函數中添加打開視頻函數
      m_hDrawDib= DrawDibOpen();

    3. 在CViewBimap類析構函數中添加關閉視頻函數

    if( m_hDrawDib != NULL)
    {
    DrawDibClose( m_hDrawDib);
    m_hDrawDib = NULL;
    }

    4. 在CViewBimap類圖形顯示函數OnPaint中添加GraphicDraw()
    voidCViewBitmap::OnPaint()
    {
    CPaintDC dc(this); // device context for painting
    GraphicDraw( );
    }

    voidCViewBitmap::GraphicDraw( void )
    {
    CClientDC dc(this); // device context for painting
    BITMAPFILEHEADER *pBitmapFileHeader;
    ULONG bfoffBits= 0;
    CPoint Wid;

    // 圖形文件名有效 (=0 BMP)
    if( mBitmapFileType < ID_BITMAP_BMP ) return;

    // 圖形文件名有效 (=0 BMP)
    // 準備顯示真彩位圖
    pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;
    bfoffBits= pBitmapFileHeader->bfOffBits;

    // 使用普通函數顯示位圖

    if( m_hDrawDib == NULL || mDispMethod == 0)
    {
    HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,
    mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,
    (LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);
    // 建立位圖
    HDC hMemDC=::CreateCompatibleDC(dc.m_hDC);// 建立內存
    HBITMAP hBitmapOld= SelectBitmap(hMemDC, hBitmap); // 選擇對象
    // 成員CRect mDispR用于指示圖形顯示區域的大小.
    // 成員CPoint mPos用于指示圖形顯示起始位置坐標.
    if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))
    mPos.x= mpBitmapInfo->biWidth - mDispR.Width() ;
    if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))
    mPos.y= mpBitmapInfo- >biHeight- mDispR.Height();
    if( mPos.x < 0 ) mPos.x= 0;
    if( mPos.y < 0 ) mPos.y= 0;

    if( mFullViewTog == 0)
    {
    // 顯示真彩位圖
    ::BitBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),
    hMemDC,mPos.x,mPos.y, SRCCOPY);
    } else {
    ::StretchBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),
    hMemDC,0,0, mpBitmapInfo- >biWidth, mpBitmapInfo-
    >biHeight, SRCCOPY);
    }
    // 結束顯示真彩位圖
    ::DeleteObject(SelectObject(hMemDC,hBitmapOld));
    // 刪 除 位 圖
    } else {

    // 使用視頻函數顯示位圖

    if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))
    mPos.x= mpBitmapInfo- >biWidth - mDispR.Width() ;
    if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))
    mPos.y= mpBitmapInfo- >biHeight- mDispR.Height();
    if( mPos.x < 0 ) mPos.x= 0;
    if( mPos.y < 0 ) mPos.y= 0;

    // 顯示真彩位圖
    DrawDibRealize( m_hDrawDib, dc.GetSafeHdc(), TRUE);

    if( mFullViewTog == 0)
    {
    Wid.x= mDispR.Width();
    Wid.y= mDispR.Height();
    // 1:1 顯示時, 不能大于圖形大小
    if( Wid.x > mpBitmapInfo- >biWidth )
    Wid.x = mpBitmapInfo- >biWidth;
    if( Wid.y > mpBitmapInfo- >biHeight)
    Wid.y = mpBitmapInfo- >biHeight;

    DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()
    , 0, 0, Wid.x, Wid.y,
    mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),
    mPos.x, mPos.y, Wid.x, Wid.y, DDF_BACKGROUNDPAL);
    } else {
    DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),
    0, 0, mDispR.Width(), mDispR.Height(),
    mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),
    0, 0, mpBitmapInfo- >biWidth, mpBitmapInfo- >biHeight,
    DDF_BACKGROUNDPAL);
    }
    }
    return;
    }

    五、使用CViewBimap類顯示BMP位圖
      1. 在Visual C++5.0中新建一個名稱為mymap工程文件,類型為MFC AppWizard[exe]。在編譯運行通過后,在WorkSpace(如被關閉,用Alt_0打開)點擊ResourceView,點擊Menu左側的+符號展開Menu條目,雙擊IDR_MAINFRAME條目,進入菜單資源編輯,在'“查看(V)”下拉式菜單(英文版為View下拉式菜單)的尾部添加“ViewBitmap”條目,其ID為ID_VIEW_BITMAP。

    2. 在Visual C++5.0中點擊下拉式菜單Project- >Add To project- >Files...,將Bitmap0.h和Bitmap0.cpp添加到工程文件中。

    3. 在Visual C++5.0中按Ctrl_W進入MFC ClassWizard,選擇類名稱為CMainFrame,ObjectIDs: ID_VIEW_BITMAP,Messages選擇Command,然后點擊Add Fuclearcase/" target="_blank" >cction按鈕,然后輸入函數名為OnViewBimap。在添加OnViewBimap后,在Member functions: 中點擊OnViewBimap條目,點擊Edit Code按鈕編輯程序代碼。代碼如下:

    void CMainFrame::OnViewBitmap()
    {
    // TODO: Add your command handler code here
    CViewBitmap *pViewBitmap= NULL;

    pViewBitmap= new CViewBitmap( "BITMAP.BMP", this);
    pViewBitmap- >ShowWindow( TRUE);
    }

    并在該程序的頭部添加#include "bitmap0.h",然后編譯運行。

    4. 找一個大一點的真彩色的BMP位圖,將它拷貝到BITMAP.BMP中。

    5. 運行時,點擊下拉式菜單“查看(V)- >ViewBitmap”(英文版為View- > ViewBitmap)即可顯示BITMAP.BMP位圖。

    六、CViewBimap類功能說明

    1. 在客戶區中帶有水平和垂直滾動條。在位圖大小大于顯示客戶區時,可以使用滾動條;在位圖大小小于顯示客戶區或全屏顯示時,滾動條無效。

    2. 在客戶區中底部帶有狀態條。狀態條中的第一格為位圖信息,第二格為位圖顯示方法,可以是使用普通函數或使用視頻函數。在第二格區域內點擊鼠標,可在兩者之間接換。第三格為位圖顯示比例,可以是1;1顯示或全屏顯示。在第三格區域內點擊鼠標,可在兩者之間接換。在全屏顯示時,如果位圖比客戶區小,則對位圖放大; 如果位圖比客戶區大,則對位圖縮小。

    3. 支持文件拖放功能??梢詮馁Y源管理器中拖動一個位圖文件到客戶區,就可以顯示該位圖。

      程序調試通過后,可以找一個較大的真彩色位圖或調整客戶區比位圖小,在全屏顯示方式下,比較使用普通函數與使用視頻函數的差別??梢钥闯?,位圖放大時兩者差別不大,但在位圖縮小時,兩者差別明顯; 使用視頻函數時位圖失真小,顯示速度快。
      還可以從控制面板中將屏幕顯示方式從真彩色顯示模式切換到256色顯示模式,再比較使用普通函數與使用視頻函數顯示同一個真彩色位圖的差別?,F在可以體會到使用視頻函數的優越性了吧。
      在全屏顯示時,位圖的xy方向比例不相同,如要保持相同比例,可在顯示程序中加以適當調整即可,讀者可自行完成。

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>