1. 程式人生 > >數字影象處理visual studio C++技術實現(楊淑瑩,張樺,陳勝勇)——第二章CDib類庫

數字影象處理visual studio C++技術實現(楊淑瑩,張樺,陳勝勇)——第二章CDib類庫

由於MFC沒有專門的處理點陣圖的庫,因此需要我們自己寫一個CDib類庫來完成點陣圖處理的一些基本操作。CDib即C型別的Dib點陣圖檔案處理,Dib是裝置無關的點陣圖檔案的意思。在CDib這個類裡面主要實現了裝載,儲存點陣圖檔案,獲取點陣圖高度,寬度,調色盤等資訊,以及影象資料部分,顏色表,點陣圖資訊部分的記憶體地址。這些資訊都是儲存在BMP檔案當中的,對於點陣圖結構在windows中已經實現了,所以程式碼不需要我們編寫,但是需要非常熟悉才行。

首先,我們要熟悉點陣圖的結構,實際上點陣圖檔案主要包括點陣圖檔案頭,點陣圖資訊頭,點陣圖顏色表,畫素資料四個部分的內容。點陣圖檔案結構在windows中已經實現了,但是我們這裡依舊需要知道其中的內容,是後面CDib類庫的基礎。

typedef struct tagBITMAPFILEHEADER {//點陣圖檔案頭

        WORD    bfType;//點陣圖檔案型別,必定為42 4d
        DWORD   bfSize;//點陣圖檔案大小
        WORD    bfReserved1;//保留位元組
        WORD    bfReserved2;//保留位元組
        DWORD   bfOffBits;/點陣圖資料的起始位置
} BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER{//點陣圖資訊頭
        DWORD      biSize;//本結構所佔尺寸
        LONG       biWidth;//點陣圖寬度,以畫素為單位
        LONG       biHeight;//點陣圖高度,以畫素為單位
        WORD       biPlanes;//裝置目標級別,為1
        WORD       biBitCount;/每個畫素的位數
        DWORD      biCompression;//壓縮型別
        DWORD      biSizeImage;//點陣圖大小
        LONG       biXPelsPerMeter;//點陣圖水平解析度
        LONG       biYPelsPerMeter;//點陣圖垂直解析度
        DWORD      biClrUsed;//點陣圖實際使用顏色數
        DWORD      biClrImportant;//點陣圖重要顏色數
} BITMAPINFOHEADER;

typedef struct tagRGBQUAD {//點陣圖顏色表
        BYTE    rgbBlue;//藍色亮度
        BYTE    rgbGreen;//綠色亮度
        BYTE    rgbRed;//紅色亮度
        BYTE    rgbReserved;//保留位

} RGBQUAD;

另外,由點陣圖資訊頭和顏色表組成了點陣圖資訊,主要記錄了點陣圖資訊頭和點陣圖顏色表的地址,其結構如下:

typedef struct tagBITMAPINFO {//點陣圖資訊
    BITMAPINFOHEADER    bmiHeader;//點陣圖資訊頭
    RGBQUAD             bmiColors[1];//顏色表
} BITMAPINFO;

然後,我們就可以來實現CDib類庫的內容了,CDib類庫繼承了CObject類,由於不是專門研究MFC,所以對CObject類還不是很瞭解,但是並不影響我們實現後面的演算法。書上的程式碼很多地方還是有一些問題,直接搬下來是沒辦法在電腦上跑出來的,很多地方還是需要在瞭解演算法思想之後自己去實現。下面是我自己的CDib.h以及CDib.cpp,放在vs2015上是可以跑出來的。

//這裡是CDib.h標頭檔案,定義了一些成員以及成員函式,和書上完全一樣

#pragma once
#ifndef _CDIB_H
#define _CDIB_H
class CDib :public CObject {//CDib類,封裝了關於BMP影象的一些基本操作
public:
    RGBQUAD *m_pRGB;//顏色表指標,定義了三元色的亮度
    BYTE *m_pDate;//圖片資料內容指標,BYTE實際上是個unsigned char型別。
    UINT m_numberofColor;//顏色的數目,UINT是unsigned int
    BOOL m_valid;//圖片是否有效
    BITMAPFILEHEADER bitmapFileHeader;//檔案頭
    BITMAPINFOHEADER *m_pbitmapInfoHeader;//檔案資訊頭指標
    BITMAPINFO *m_pbitmapInfo;//點陣圖資訊指標,由檔案資訊和顏色表組成
    BYTE *pDib;//
    DWORD size;//檔案尺寸,DWORD為unsigned long
public:
    CDib();//建構函式
    ~CDib();//解構函式
    char m_fileName[256];//檔名
    char* GetFileName();//獲取檔名
    BOOL IsValid();//判斷檔案是否有效
    DWORD GetSize();//圖片尺寸
    UINT GetWidth();//圖片寬度
    UINT GetHeight();//圖片高度
    UINT GetNumberOfColors();//圖片顏色數
    RGBQUAD *GetRGB();//獲取顏色表
    BYTE *GetData();//獲取圖片資料
    BITMAPINFO *GetInfo();//獲取圖片點陣圖資訊
    WORD PaletteSize(LPBYTE lpDIB);//獲取調色盤尺寸,LPBYTE即BYTE的遠指標
    WORD DIBNumColors(LPBYTE lpDIB);//獲取顏色數目
    void SaveFile(const CString filename);//儲存檔案,CString是MFC定義的一個字串型別
    void LoadFile(CString dibFileName);//載入檔案
};
#endif 

//這裡是CDib.cpp檔案的內容主要是實現了CDib標頭檔案的成員函式

#include "stdafx.h"
#include"CDib.h"
#include<windowsX.h>

CDib::CDib()//建構函式,size初始化為0
{
    size = 0;
}


CDib::~CDib()
{
    GlobalFreePtr(m_pbitmapInfo);//釋放點陣圖資訊記憶體
}


BOOL CDib::IsValid()
{
    return m_valid;
}

DWORD CDib::GetSize()
{
    if (m_pbitmapInfoHeader->biSizeImage)
        return m_pbitmapInfoHeader->biSizeImage;
    else {
        DWORD height = (DWORD)GetHeight();
        DWORD width = (DWORD)GetWidth();
        return height*width;
    }
}

UINT CDib::GetHeight()
{
    return m_pbitmapInfoHeader->biHeight;
}

UINT CDib::GetWidth()
{
    return m_pbitmapInfoHeader->biWidth;
}


char* CDib::GetFileName()
{
    return m_fileName;
}

UINT CDib::GetNumberOfColors()//獲取顏色數目
{
    int numberofcolors;//記錄顏色數目

    //當為標頭檔案中沒有儲存使用顏色數目,且顏色位數合法時

    if (m_pbitmapInfoHeader->biClrUsed == 0 && m_pbitmapInfoHeader->biBitCount < 9)
    {
        switch (m_pbitmapInfoHeader->biBitCount)
        {
        case 1: numberofcolors = 2; break; //2色
        case 4:numberofcolors = 16; break ;//16色
        case 8:numberofcolors = 256;          //256色

        }
    }
    else
        numberofcolors = (int)m_pbitmapInfoHeader->biClrUsed;//否則直接返回使用的顏色數目
    return numberofcolors;
}


BYTE* CDib::GetData()
{
    return m_pDate;
}


BITMAPINFO *CDib::GetInfo()
{
    return m_pbitmapInfo;
}

WORD CDib::PaletteSize(LPBYTE lpDIB)
{
    return (DIBNumColors(lpDIB) * sizeof(RGBTRIPLE));
}

WORD CDib::DIBNumColors(LPBYTE lpDIB)
{
    WORD wBitCount;//點陣圖的位數
    wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;
    switch (wBitCount)
    {
    case 1:return 2;
    case 4:return 16;
    case 8:return 256;
    default:return 0;
    }
}


void CDib::LoadFile(CString dibFileName)
{
    //strcpy_s(m_fileName,(const char*)&dibFileName);//將傳入的檔名複製到CDib類中定義的m_fileName中
    CFile dibFile((LPCTSTR)dibFileName, CFile::modeRead);//以檔名初始化CFile物件dibFile,dibFile成為該檔案的一個副本
    dibFile.Read((void*)&bitmapFileHeader, sizeof(BITMAPFILEHEADER));//讀取該檔案的檔案資訊頭到dibFile物件中
    if (bitmapFileHeader.bfType == 0x4d42)//判斷是否為點陣圖
    {
        DWORD fileLength = dibFile.GetLength();//獲取檔案長度
        size = fileLength - sizeof(BITMAPFILEHEADER);//獲取除點陣圖檔案頭之外的長度size
        pDib = (BYTE*)GlobalAllocPtr(GMEM_MOVEABLE, size);//動態分配size大小的記憶體到pDib中
        dibFile.Read((void*)pDib, size);//讀取檔案後半部分到dibFile中
        dibFile.Close();//關閉檔案
        m_pbitmapInfo = (BITMAPINFO*)pDib;//m_pbitmapInfo指標指向除檔案頭之外的部分
        m_pbitmapInfoHeader = (BITMAPINFOHEADER*)pDib;//m_pbitmapInfoHeader指向除檔案頭之外的部分
        m_pRGB = (RGBQUAD*)(pDib + m_pbitmapInfoHeader->biSize);//m_pRGB指向顏色起始地址
        int m_numberOfColors = GetNumberOfColors();//獲取色數
        if (m_pbitmapInfoHeader->biClrUsed == 0)
            m_pbitmapInfoHeader->biClrUsed = m_numberOfColors;
        DWORD colorTableSize = m_numberOfColors * sizeof(RGBQUAD);//獲取顏色表大小
        m_pDate = pDib + m_pbitmapInfoHeader->biSize + colorTableSize;//指向點陣圖資料開始部分
        if (m_pRGB == (RGBQUAD*)m_pDate)//若無顏色表,則m_pRGB置空
            m_pRGB = NULL;
        m_pbitmapInfoHeader->biSizeImage = GetSize();//獲取圖片資料內容長度
        m_valid = TRUE;
    }
    else
    {
        m_valid = FALSE;
        AfxMessageBox((UINT)"not .bmp");
    }
}

void CDib::SaveFile(const CString filename)
{
    strcpy_s(m_fileName, (const char*)&filename);
    CFile dibFile((LPCTSTR)m_fileName, CFile::modeCreate | CFile::modeWrite);//以寫的方式開啟檔案
    dibFile.Write((void*)&bitmapFileHeader, sizeof(BITMAPCOREHEADER));//將檔案頭寫入檔案
    dibFile.Write((void*)pDib, size);//將檔案其它部分寫入檔案
    dibFile.Close();//關閉檔案

}

RGBQUAD *CDib::GetRGB()//獲取調色盤指標
{
    return m_pRGB;
}

後面的內容是實現影象的顯示和一些特效顯示的內容,需要再建立一個CDynSplitView2類庫,來實現點陣圖的顯示功能。其

中最重要的是一個WINAPI的函式,即StretchDIBits();具體引數的內容在書中有詳細的介紹,這裡需要特別熟悉,因為本章的顯示

圖片內容基本上都是關於這個函式的操作。下面就是CDynSplitView2的類庫,類庫函式名和書上完全一樣,但實現方式可能有所

不同,而且書上的內容確實是跑不出來的。為了方便,我是把它和CDib類統一放在CDib.h檔案裡面的,而且其中成員函式的實現

也是放在CDib.cpp中的。

class CDynSplitView2 :public CView
{
public:
    CPalette *hPalette;//調色盤指標
    CDib *dib;//指向CDib類的一個指標
public:
    CPalette *CreatBitmapPalette(CDib *pBitmap);//為要顯示的點陣圖建立調色盤
    void OnDraw(CDC *pD);//顯示圖片函式,需傳入裝置上下文(用GetDC()函式獲取),和CDib類的指標
    void OnXiangXia(CDC *pDC);//向下掃描特效顯示
    void GetDib(CDib *pcdib);//獲取CDib類物件的指標
    void OnXiangShang(CDC *pDC);//向下顯示
    void OnXiangYou(CDC *pDC);//向右顯示
    void OnXiangZuo(CDC *pDC);//向左顯示
    void ClearDlg(CDC *pDC);//清空對話方塊
    void OnJianXian(CDC *pDC);//漸顯
    void OnMaSaiKe(CDC *pDC);//馬賽克顯示
    void OnShuiPingYouYi(CDC *Pdc);//水平右移
    void OnChuiZhiShangYi(CDC *pDC);//垂直上移
    void OnJiaoChaFeiRu(CDC *pDC);//交叉飛入
    void OnZhongJianKuoZhang(CDC *pDC);//中間擴充套件
    void OnZhongJianShouSuo(CDC *pDC);//中間收縮
    void OnShuiPingShanTiao(CDC *pDC);//水平柵條
    void OnChuiZhiShanTiao(CDC *pDC);//垂直柵條
    void OnBaiYeChuang(CDC *pDC);//百葉窗顯示
    void OnChuiZhiBaiYeChuang(CDC *pDC);//垂直百葉窗
};

//下面是成員函式的實現

void CDynSplitView2::OnDraw(CDC *pDC)
{
    int m_scale = 1;//控制縮放比例
    BYTE * pBitmapData = dib->GetData();//獲取點陣圖的資料部分
    LPBITMAPINFO pBitmapInfo = dib->GetInfo();//獲取點陣圖資訊
    int bitmapHeight = dib->GetHeight();//獲取點陣圖高度
    int bitmapWidth = dib->GetWidth();//獲取點陣圖寬度
    int scaledWidth = (int)(bitmapWidth*m_scale);//點陣圖實際的顯示寬度,為點陣圖原寬度X控制縮放比例
    int scaledHeight = (int)(bitmapHeight*m_scale);
    if (dib->GetRGB())//判斷該點陣圖是否具有調色盤
    {
        CRect rect(0,0,1000,1000);
        CBrush brush(RGB(255, 255, 255));
        pDC->FillRect(&rect,&brush);
        CPalette *hPalette = CreatBitmapPalette(dib);//建立調色盤
        CPalette *hOldPalette = pDC->SelectPalette(hPalette, true);//將自己建立的調色盤運用到裝置上下文中
        pDC->RealizePalette();//實現調色盤
                              //繪圖
        ::StretchDIBits(pDC->GetSafeHdc(), 20, 0, scaledWidth, scaledHeight, 20, 0, bitmapWidth, bitmapHeight, pBitmapData, pBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
        pDC->SelectPalette(hOldPalette, true);//調出舊調色盤
        ::DeleteObject(hPalette);//刪除舊調色盤
    }
    else//沒有調色盤時,採用系統自帶24位真彩色
    {
        ::StretchDIBits(pDC->GetSafeHdc(), 20, 0, scaledWidth, scaledHeight, 20, 0, bitmapWidth, bitmapHeight, pBitmapData, pBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
    }

}


void CDynSplitView2::OnXiangXia(CDC *pDC)
{
    //CDC *pDC=GetDC();
    CRect rect(0, 0, 1000, 1000);//一個矩形類
    CBrush brush(RGB(255, 255, 255));
    pDC->FillRect(&rect, &brush);//將整個矩陣用白色填滿,影象的區域是不包含右邊和下邊
    //    clearmem();//複製影象資料,取得原始影象的拷貝檔案???找不到
    //CDocument *pDoc = GetDocument();//返回與本檢視連線的文件類物件指標,這邊改了
    BYTE* pBitmapData = dib->GetData();//將書中的偽變數換成了自己設的
    LPBITMAPINFO pBitmapInfo = dib->GetInfo();
    int bitmapHeight = dib->GetHeight();
    int bitmapWidth = dib->GetWidth();
    if (dib->GetRGB())//如果顏色表指標不為空
    {
        
        CPalette* hPalette = CreatBitmapPalette(dib);
        CPalette* hOldPalette = pDC->SelectPalette(hPalette, true);
        pDC->RealizePalette();
        for (int j = 0; j<bitmapHeight; j++)
        {
            //修改了第7個引數,比原書-1,書那樣是不對的
            //影象橫著是x軸,豎著向下是y軸
            ::StretchDIBits(pDC->GetSafeHdc(), 20, j, bitmapWidth+20, 1, 20, bitmapHeight - j - 1, bitmapWidth, 1, pBitmapData, pBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            //1是裝置上下文控制代碼,2、3引數是繪製圖像左上角座標,4、5是繪製圖像的寬度和高度,6、7是要繪製的原圖的左下角座標(--假如座標超出了,繪製圖像相應區域會以白色代替--)(注意,點陣圖行的儲存是顛倒的,所以是倒著複製),8、9是原圖寬度和高度,10是指向影象資料的指標,11是指向影象BITMAPINFO結構的指標,12是bmiColors包含真實的RGB值還是調色盤中的索引值,13指定要進行的光柵運算
            //如果目標矩陣大於要複製的原圖區域就進行行和列的拉伸,反之利用光柵操作進行壓縮
            Sleep(5);//延時5毫秒
        }
        pDC->SelectPalette(hOldPalette, true);
        ::DeleteObject(hPalette);
    }
    else {
        CRect rect(0, 0, 1000, 1000);//一個矩形類
        CBrush brush(RGB(255, 255, 255));
        pDC->FillRect(&rect, &brush);
        for (int j = 0; j<bitmapHeight; j++)
        {    
            ::StretchDIBits(pDC->GetSafeHdc(), 20, j, bitmapWidth+20, 1, 20, bitmapHeight - j - 1, bitmapWidth, 1, pBitmapData, pBitmapInfo, DIB_RGB_COLORS, SRCCOPY);

            Sleep(5);//延時5毫秒
        }
    }
}

void CDynSplitView2::OnXiangShang(CDC *pDC)
{
    CRect rect(0, 0, 1000, 1000);
    CBrush brush(RGB(255, 255, 255));
    pDC->FillRect(&rect, &brush);
    int bitmapHeight = dib->GetHeight();
    int bitmapWidth = dib->GetWidth();
    LPBITMAPINFO bitmapInfo = dib->GetInfo(); 
    BYTE* bitmapData = dib->GetData();
    if (dib->GetRGB())
    {
        CPalette *hPalette = CreatBitmapPalette(dib);
        CPalette *hOldPalette = pDC->SelectPalette(hPalette,true);
        pDC->RealizePalette();
        for (size_t i = 0; i != bitmapHeight; ++i)
        {
            ::StretchDIBits(pDC->GetSafeHdc(), 20, bitmapHeight - i + 1, bitmapWidth, 1, 20, i, bitmapWidth, 1, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(5);
        }
        pDC->SelectPalette(hOldPalette,true);
        ::DeletePalette(hPalette);
    }
    else
    {
        for (size_t i = 0; i != bitmapHeight; ++i)
        {
            ::StretchDIBits(pDC->GetSafeHdc(), 20, bitmapHeight - i + 1, bitmapWidth, 1, 20, i, bitmapWidth, 1, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(5);
        }
    }

}


void CDynSplitView2::OnXiangYou(CDC *pDC)
{
    CRect rect(0, 0, 1000, 1000);
    CBrush brush(RGB(255, 255, 255));
    pDC->FillRect(&rect,&brush);
    int bitmapHeight = dib->GetHeight();
    int bitmapWideth = dib->GetWidth();
    BYTE *bitmapData = dib->GetData();
    LPBITMAPINFO bitmapInfo = dib->GetInfo();
    if (dib->GetRGB())
    {
        CPalette *hPalette;
        hPalette = CreatBitmapPalette(dib);
        CPalette *hOldPalette = pDC->SelectPalette(hPalette,true);
        pDC->RealizePalette();
        for (size_t i = 0; i != bitmapWideth; ++i)
        {
            ::StretchDIBits(pDC->GetSafeHdc(), 20 + i, 20, 1, bitmapHeight, 20 + i, 20, 1, bitmapHeight, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(5);
        }
        pDC->SelectPalette(hOldPalette, true);
        ::DeletePalette(hPalette);

    }
    else
    {
        for (size_t i = 0; i != bitmapWideth; ++i)
        {
            ::StretchDIBits(pDC->GetSafeHdc(), 20 + i, 20, 1, bitmapHeight, 20 + i, 20, 1, bitmapHeight, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(5);
        }
    }
}

void CDynSplitView2::OnXiangZuo(CDC *pDC)
{
    CRect rect(0, 0, 1000, 1000);
    CBrush brush(RGB(255, 255, 255));
    pDC->FillRect(&rect, &brush);
    int bitmapHeight = dib->GetHeight();
    int bitmapWideth = dib->GetWidth();
    BYTE *bitmapData = dib->GetData();
    LPBITMAPINFO bitmapInfo = dib->GetInfo();
    if (dib->GetRGB())
    {
        CPalette *hPalette;
        hPalette = CreatBitmapPalette(dib);
        CPalette *hOldPalette = pDC->SelectPalette(hPalette, true);
        pDC->RealizePalette();
        for (size_t i = 0; i != bitmapWideth; ++i)
        {
            ::StretchDIBits(pDC->GetSafeHdc(), bitmapWideth - i + 20, 20, 1, bitmapHeight, bitmapWideth - i + 20, 20, 1, bitmapHeight, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(5);
        }
        pDC->SelectPalette(hOldPalette, true);
        ::DeletePalette(hPalette);

    }
    else
    {
        for (size_t i = 0; i != bitmapWideth; ++i)
        {
            ::StretchDIBits(pDC->GetSafeHdc(), bitmapWideth - i+20, 20, 1,bitmapHeight , bitmapWideth - i + 20, 20, 1, bitmapHeight, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(5);
        }
    }
}

void CDynSplitView2::ClearDlg(CDC *pDC)//清空對話方塊
{
    CRect rect(0, 0, 1000, 1000);
    CBrush brush(RGB(255, 255, 255));
    pDC->FillRect(&rect, &brush);
}


void CDynSplitView2::OnJianXian(CDC *pDC)
{
    //先清空對話方塊
    CRect rect(0, 0, 1000, 1000);
    CBrush brush(RGB(255, 255, 255));
    pDC->FillRect(&rect, &brush);
    //獲取必要的影象資訊
    int bitmapHeight = dib->GetHeight();
    int bitmapWideth = dib->GetWidth();
    BYTE *bitmapData = dib->GetData();
    LPBITMAPINFO bitmapInfo = dib->GetInfo();
    if (dib->GetRGB())//若影象有自帶調色盤
    {
        CPalette *hPalette;
        hPalette = CreatBitmapPalette(dib);//建立新調色盤
        CPalette *hOldPalette = pDC->SelectPalette(hPalette, true);//選擇新調色盤,並返回老調色盤
        pDC->RealizePalette();//使選擇的調色盤生效
        LPBYTE temp, temp1, temp2;//宣告三個BYTE型別的指標
        temp = new BYTE[bitmapWideth*bitmapHeight];//對temp新分配一段長度為圖片資料部分大小的指標
        memset(temp, 0, bitmapWideth*bitmapHeight);//將temp所指向的記憶體置全部為0
        for (size_t n = 0; n != 256; ++n)//迴圈256次
        {
            temp1 = temp;//temp1指向新分配的記憶體區域temp
            temp2 = bitmapData;//temp2指向圖片的資料部分
            for (size_t i = 0; i != bitmapWideth; ++i)//遍歷圖片中的每一個畫素點
            {
                for (size_t j = 0; j != bitmapHeight; ++j)
                {
                    *temp1 = (*temp2)*n / 256;//將亮度置為原來的n/256
                    temp1++;
                    temp2++;
                }
            }
            //顯示該亮度下的圖片
            ::StretchDIBits(pDC->GetSafeHdc(), 20, 20, bitmapWideth, bitmapHeight, 20, 20, bitmapWideth, bitmapHeight, temp, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(1);
        }
        pDC->SelectPalette(hOldPalette, true);//調色盤還原
        ::DeletePalette(hPalette);//刪除新生成的調色盤
    }
    else//如果圖片沒有自帶的調色盤
    {
        //同上,這裡對於沒有自帶調色盤的圖片的顯示有些問題,但是我們還沒有想出解決的辦法
        LPBYTE temp, temp1, temp2;
        temp = new BYTE[bitmapWideth*bitmapHeight];
        memset(temp, 0, bitmapWideth*bitmapHeight);
        for (size_t n = 0; n != 256; ++n)
        {
            temp1 = temp;
            temp2 = bitmapData;
            for (size_t i = 0; i != bitmapWideth; ++i)
            {
                for (size_t j = 0; j != bitmapHeight; ++j)
                {
                    *temp1 = (*temp2)*n / 256;
                    temp1++;
                    temp2++;
                }
            }
            ::StretchDIBits(pDC->GetSafeHdc(), 20, 20, bitmapWideth, bitmapHeight, 20, 20, bitmapWideth, bitmapHeight, temp, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(1);
        }
    }
}


void CDynSplitView2::OnMaSaiKe(CDC *pDC)
{
    //設定一個block結構體,每次顯示的小方塊
    struct Block {
        int x, y;//每次顯示時左上角
        bool flag;//0表示未顯示,1表示已顯示
    };
    //先清空對話方塊
    CRect rect(0, 0, 1000, 1000);
    CBrush brush(RGB(255, 255, 255));
    pDC->FillRect(&rect, &brush);
    //獲取必要的影象資訊
    int bitmapHeight = dib->GetHeight();
    int bitmapWideth = dib->GetWidth();
    BYTE *bitmapData = dib->GetData();
    LPBITMAPINFO bitmapInfo = dib->GetInfo();
    //馬賽克顯示的必要引數
    int mx = 0, my = 0;//劃分塊的輔助引數
    int rddx = 0, rddy = 0;//是否有多餘的塊,即以10為長度劃分之後不足10的部分,以新增塊表示
    int blockNum = 0;//總塊數
    if (bitmapWideth % 10) rddx = 1;//有多餘的塊
    if (bitmapHeight % 10) rddy = 1;
    blockNum = (bitmapWideth / 10 + rddx)*(bitmapHeight / 10 + rddy);//計算總的塊數
    Block *block = new Block[blockNum];//分配總塊數的記憶體空間

    //顯示部分函式
    if(dib->GetRGB())
    {
        CPalette *hPalette;
        hPalette = CreatBitmapPalette(dib);//建立新調色盤
        CPalette *hOldPalette = pDC->SelectPalette(hPalette, true);//選擇新調色盤,並返回老調色盤
        pDC->RealizePalette();//使選擇的調色盤生效
        for (int i = 0; i != blockNum; ++i)//遍歷每塊
        {
            block[i].x = mx;//為塊的邏輯左上角x座標賦值,最開始為0,依次加10
            block[i].y = my;//為y賦值,一直為my當前值,只有換行時my才會加10
            block[i].flag = 0;//標記未顯示
            mx += 10;
            if (mx > bitmapWideth)//如果mx大於影象長度,則需要換行
            {
                mx = 0;//mx重置為0
                my += 10;//my加10
            }
        }

        int count = 0,n;//count記錄已經顯示了的塊數,n表示下標
        while (count!=blockNum)//未全部顯示
        {
            n = (int)((double)blockNum*rand()/RAND_MAX);//隨機生成下標n
            if (block[n].flag==0)  //如果未顯示
            {
                block[n].flag = 1; //標記未已顯示
                count++;           //已顯示塊數加一
                int showx = block[n].x;
                int showy = block[n].y;
                //繪圖,這裡的引數解釋一下,第一個引數為裝置上下文,第2,3,4,5分別為邏輯左上角座標以及寬度,高度,也就是顯示在
                //螢幕上的位置,引數6,7,8,9,10,為實際圖片資料在記憶體中儲存位置的左上角座標,和寬度高度,由於點陣圖在記憶體中儲存
                //時行順序和實際顯示顛倒,因此對於邏輯座標(0,0)的點,其記憶體位置就在(圖片高度-0-10),其它的以此類推。
                    ::StretchDIBits(pDC->GetSafeHdc(),showx,showy,10,10,showx,bitmapHeight-showy-10,10,10,bitmapData,bitmapInfo,DIB_RGB_COLORS,SRCCOPY );
                    Sleep(5);
            }
        }
        pDC->SelectPalette(hOldPalette, true);//調色盤還原
        ::DeletePalette(hPalette);//刪除新生成的調色盤
        delete[] block;//釋放block
    }
    else//和上面一樣
    {
        for (int i = 0; i != blockNum; ++i)
        {
            block[i].x = mx;
            block[i].y = my;
            block[i].flag = 0;
            mx += 10;
            if (mx > bitmapWideth)
            {
                mx = 0;
                my += 10;
            }
        }

        int count = 0, n;
        while (count != blockNum)
        {
            n = (int)((double)blockNum*rand() / RAND_MAX);
            if (block[n].flag == 0)
            {
                block[n].flag = 1;
                count++;
                int showx = block[n].x;
                int showy = block[n].y;
                ::StretchDIBits(pDC->GetSafeHdc(), showx, showy, 10, 10, showx, bitmapHeight - showy - 10, 10, 10, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
                Sleep(5);
            }
        }
    }
}


void CDynSplitView2::OnShuiPingYouYi(CDC *pDC)
{
    //重新整理對話方塊
    CRect rect(0, 0, 1000, 1000);
    CBrush brush(RGB(255, 255, 255));
    pDC->FillRect(&rect, &brush);
    //獲取必要的影象資訊
    int bitmapHeight = dib->GetHeight();
    int bitmapWideth = dib->GetWidth();
    BYTE *bitmapData = dib->GetData();
    LPBITMAPINFO bitmapInfo = dib->GetInfo();

    if (dib->GetRGB())
    {
        CPalette *hPalette;
        hPalette = CreatBitmapPalette(dib);//建立新調色盤
        CPalette *hOldPalette = pDC->SelectPalette(hPalette, true);//選擇新調色盤,並返回老調色盤
        pDC->RealizePalette();//使選擇的調色盤生效
        int showx = 0;//用於控制每次顯示的寬度
        for (size_t i = 0; i != bitmapWideth; ++i)//每次多顯示一列畫素點,一共迴圈寬度次數
        {
            //重新整理螢幕
            CRect rect(0, 0, 1000, 1000);
            CBrush brush(RGB(255, 255, 255));
            pDC->FillRect(&rect, &brush);
            //每次顯示的寬度加一
            showx += 1;
            //顯示
            ::StretchDIBits(pDC->GetSafeHdc(), 0, 0, showx, bitmapHeight, bitmapWideth - showx - 1, 0, showx, bitmapHeight, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(5);
        }
        pDC->SelectPalette(hOldPalette, true);//調色盤還原
        ::DeletePalette(hPalette);//刪除新生成的調色盤
    }
    else
    {
        int showx = 0, showy = 0;
        for (size_t i = 0; i != bitmapWideth; ++i)
        {
            CRect rect(0, 0, 1000, 1000);
            CBrush brush(RGB(255, 255, 255));
            pDC->FillRect(&rect, &brush);
            showx += 1;
            showy += 1;
            ::StretchDIBits(pDC->GetSafeHdc(), 0, 0, showx, bitmapHeight, bitmapWideth - showy - 1, 0, showx, bitmapHeight, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(5);
        }
    }

}


void CDynSplitView2::OnChuiZhiShangYi(CDC *pDC)
{
    CRect rect(0, 0, 1000, 1000);
    CBrush brush(RGB(255, 255, 255));
    pDC->FillRect(&rect, &brush);
    //獲取必要的影象資訊
    int bitmapHeight = dib->GetHeight();
    int bitmapWideth = dib->GetWidth();
    BYTE *bitmapData = dib->GetData();
    LPBITMAPINFO bitmapInfo = dib->GetInfo();
    if (dib->GetRGB())
    {
        CPalette *hPalette;
        hPalette = CreatBitmapPalette(dib);//建立新調色盤
        CPalette *hOldPalette = pDC->SelectPalette(hPalette, true);//選擇新調色盤,並返回老調色盤
        pDC->RealizePalette();//使選擇的調色盤生效
        for (size_t i = 0; i != bitmapHeight; ++i)
        {
            CRect rect(0, 0, 1000, 1000);
            CBrush brush(RGB(255, 255, 255));
            pDC->FillRect(&rect, &brush);
            ::StretchDIBits(pDC->GetSafeHdc(),0, bitmapHeight - i - 1, bitmapWideth,i+1,0,bitmapHeight - 1 - i,bitmapWideth,i+1,bitmapData,bitmapInfo,DIB_RGB_COLORS,SRCCOPY);
            Sleep(5);
        }
        pDC->SelectPalette(hOldPalette, true);//調色盤還原
        ::DeletePalette(hPalette);//刪除新生成的調色盤
    }
    else {
        for (size_t i = 0; i != bitmapHeight; ++i)
        {
            CRect rect(0, 0, 1000, 1000);
            CBrush brush(RGB(255, 255, 255));
            pDC->FillRect(&rect, &brush);
            ::StretchDIBits(pDC->GetSafeHdc(), 0, bitmapHeight - i - 1, bitmapWideth, i + 1, 0, bitmapHeight - 1 - i, bitmapWideth, i + 1, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(5);
        }
    }
}

void CDynSplitView2::OnJiaoChaFeiRu(CDC *pDC)
{
    //重新整理螢幕
    CRect rect(0, 0, 1000, 1000);
    CBrush brush(RGB(255,255,255));
    pDC->FillRect(&rect,&brush);
    //獲取圖片資訊
    int bitmapHeight = dib->GetHeight();
    int bitmapWideth = dib->GetWidth();
    BYTE *bitmapData = dib->GetData();
    LPBITMAPINFO bitmapInfo = dib->GetInfo();
    if (dib->GetRGB())
    {

        CPalette *hPalette;
        hPalette = CreatBitmapPalette(dib);//建立新調色盤
        CPalette *hOldPalette = pDC->SelectPalette(hPalette, true);//選擇新調色盤,並返回老調色盤
        pDC->RealizePalette();//使選擇的調色盤生效
        for (size_t i = 0; i != bitmapWideth; ++i)
        {
            CRect rect(0, 0, 1000, 1000);
            CBrush brush(RGB(255, 255, 255));
            pDC->FillRect(&rect, &brush);
            //分別對上半部分和下半部分實現向左和向右平移
            ::StretchDIBits(pDC->GetSafeHdc(),0,0,i+1,bitmapHeight/2,0,bitmapHeight/2,i+1,bitmapHeight/2,bitmapData,bitmapInfo,DIB_RGB_COLORS,SRCCOPY);
            ::StretchDIBits(pDC->GetSafeHdc(), bitmapWideth-i, bitmapHeight / 2, 1 + i, bitmapHeight / 2, 0, 0, 1 + i, bitmapHeight / 2, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(5);
        }
        pDC->SelectPalette(hOldPalette, true);//調色盤還原
        ::DeletePalette(hPalette);//刪除新生成的調色盤
    }
    else
    {
        for (size_t i = 0; i != bitmapWideth; ++i)
        {
            CRect rect(0, 0, 1000, 1000);
            CBrush brush(RGB(255, 255, 255));
            pDC->FillRect(&rect, &brush);
            ::StretchDIBits(pDC->GetSafeHdc(), 0, 0, i + 1, bitmapHeight / 2, 0, bitmapHeight / 2, i + 1, bitmapHeight / 2, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            ::StretchDIBits(pDC->GetSafeHdc(), bitmapWideth - i, bitmapHeight / 2, 1 + i, bitmapHeight / 2, 0, 0, 1 + i, bitmapHeight / 2, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(25);
        }
    }
}


void CDynSplitView2::OnZhongJianKuoZhang(CDC *pDC) {
    //重新整理螢幕
    CRect rect(0, 0, 1000, 1000);
    CBrush brush(RGB(255, 255, 255));
    pDC->FillRect(&rect, &brush);
    //獲取圖片資訊
    int bitmapHeight = dib->GetHeight();
    int bitmapWideth = dib->GetWidth();
    BYTE *bitmapData = dib->GetData();
    LPBITMAPINFO bitmapInfo = dib->GetInfo();
    if (dib->GetRGB())
    {

        CPalette *hPalette;
        hPalette = CreatBitmapPalette(dib);//建立新調色盤
        CPalette *hOldPalette = pDC->SelectPalette(hPalette, true);//選擇新調色盤,並返回老調色盤
        pDC->RealizePalette();//使選擇的調色盤生效
        for (size_t i = 0; i != bitmapWideth; ++i)
        {
            CRect rect(0, 0, 1000, 1000);
            CBrush brush(RGB(255, 255, 255));
            pDC->FillRect(&rect, &brush);
            //從中間開始分別向上,向下掃描
            ::StretchDIBits(pDC->GetSafeHdc(), 0, bitmapHeight / 2 - 1 - i, bitmapWideth, 1 + i, 0, bitmapHeight / 2, bitmapWideth, 1 + i, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            ::StretchDIBits(pDC->GetSafeHdc(), 0, bitmapHeight / 2, bitmapWideth, 1 + i, 0, bitmapHeight / 2 - 1 - i, bitmapWideth, 1 + i, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(5);
        }
        pDC->SelectPalette(hOldPalette, true);//調色盤還原
        ::DeletePalette(hPalette);//刪除新生成的調色盤
    }
    else
    {
        for (size_t i = 0; i != bitmapHeight/2; ++i)
        {
            CRect rect(0, 0, 1000, 1000);
            CBrush brush(RGB(255, 255, 255));
            pDC->FillRect(&rect, &brush);
            ::StretchDIBits(pDC->GetSafeHdc(), 0, bitmapHeight/2-1-i, bitmapWideth, 1 + i, 0, bitmapHeight / 2, bitmapWideth, 1 + i, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            ::StretchDIBits(pDC->GetSafeHdc(), 0, bitmapHeight / 2, bitmapWideth, 1 + i, 0, bitmapHeight/2-1-i, bitmapWideth,1 + i, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(5);
        }
    }
}

void CDynSplitView2::OnZhongJianShouSuo(CDC *pDC)
{
    //重新整理螢幕
    CRect rect(0, 0, 1000, 1000);
    CBrush brush(RGB(255, 255, 255));
    pDC->FillRect(&rect, &brush);
    //獲取圖片資訊
    int bitmapHeight = dib->GetHeight();
    int bitmapWideth = dib->GetWidth();
    BYTE *bitmapData = dib->GetData();
    LPBITMAPINFO bitmapInfo = dib->GetInfo();
    if (dib->GetRGB())
    {
        CPalette *hPalette;
        hPalette = CreatBitmapPalette(dib);//建立新調色盤
        CPalette *hOldPalette = pDC->SelectPalette(hPalette, true);//選擇新調色盤,並返回老調色盤
        pDC->RealizePalette();//使選擇的調色盤生效
        for (size_t i = 0; i != bitmapWideth / 2; ++i)
        {
            ::StretchDIBits(pDC->GetSafeHdc(),0,0,bitmapWideth,1+i,0,bitmapHeight/2,bitmapWideth,1+i,bitmapData,bitmapInfo,DIB_RGB_COLORS,SRCCOPY);
            ::StretchDIBits(pDC->GetSafeHdc(), 0, bitmapHeight-1-i, bitmapWideth, 1 + i,0,0,bitmapWideth,1+i,bitmapData,bitmapInfo,DIB_RGB_COLORS,SRCCOPY);
            Sleep(5);
        }
        pDC->SelectPalette(hOldPalette, true);//調色盤還原
        ::DeletePalette(hPalette);//刪除新生成的調色盤pDC->SelectPalette(hOldPalette, true);//調色盤還原
    }
    else {
        for (size_t i = 0; i != bitmapWideth / 2; ++i)
        {
            ::StretchDIBits(pDC->GetSafeHdc(), 0, 0, bitmapWideth, 1 + i, 0, bitmapHeight / 2, bitmapWideth, 1 + i, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            ::StretchDIBits(pDC->GetSafeHdc(), 0, bitmapHeight - 1 - i, bitmapWideth, 1 + i, 0, 0, bitmapWideth, 1 + i, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(5);
        }
    }
}


void CDynSplitView2::OnShuiPingShanTiao(CDC *pDC)
{
    //block結構體用於分塊
    struct Block {
        int x, y;//記錄每一塊左上角
    };
    //重新整理螢幕
    CRect rect(0, 0, 1000, 1000);
    CBrush brush(RGB(255, 255, 255));
    pDC->FillRect(&rect, &brush);
    //獲取圖片資訊
    int bitmapHeight = dib->GetHeight();
    int bitmapWideth = dib->GetWidth();
    BYTE *bitmapData = dib->GetData();
    LPBITMAPINFO bitmapInfo = dib->GetInfo();
    //分塊,以10為單位進行分塊
    int rddx = 0;//表示X方向上是否有多餘的塊
    if (bitmapWideth % 10 != 0) rddx++;//若圖片寬度不能被10整除,則此時有多餘的塊,rddx加一
    int bx = (bitmapWideth  /10) + rddx;//總塊數
    Block *block = new Block[bx];//分配塊數的記憶體
    int temp = 0;//臨時變數,記錄下一塊的x的位置
    for (size_t i = 0; i != bx; ++i)//以10為單位進行分塊
    {
        block[i].x = temp;
        temp += 10;
        block[i].y = 0;
    }

    if (dib->GetRGB())
    {
        CPalette *hPalette;
        hPalette = CreatBitmapPalette(dib);//建立新調色盤
        CPalette *hOldPalette = pDC->SelectPalette(hPalette, true);//選擇新調色盤,並返回老調色盤
        pDC->RealizePalette();//使選擇的調色盤生效
        for (size_t i = 0; i != bx; ++i)//先將偶數塊顯示出來
        {
            int mx = block[i].x;
            int my = block[i].y;
            //如果該塊為偶數快,則畫出該塊
            if ((i+2) % 2==0) ::StretchDIBits(pDC->GetSafeHdc(),mx,my,10,bitmapHeight,mx,my,10,bitmapHeight, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
        }
        for (size_t i = 0; i != bx; ++i)//將奇數塊掃描顯示
        {
            int mx = block[i].x;
            int my = block[i].y;
            if((i+2)%2!=0)//如果為奇數塊
                for (size_t j = 0; j != 10; ++j)//向右掃描顯示,每次顯示長度為1
                {
                    ::StretchDIBits(pDC->GetSafeHdc(), mx, my, 1+j, bitmapHeight, mx, my, 1+j, bitmapHeight, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
                    Sleep(20);
                }
        }
        pDC->SelectPalette(hOldPalette, true);//調色盤還原
        ::DeletePalette(hPalette);//刪除新生成的調色盤pDC->SelectPalette(hOldPalette, true);//調色盤還原
    }
    else {
        for (size_t i = 0; i != bx; ++i)
        {
            int mx = block[i].x;
            int my = block[i].y;
            if ((i + 2) % 2 == 0) ::StretchDIBits(pDC->GetSafeHdc(), mx, my, 10, bitmapHeight, mx, my, 10, bitmapHeight, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
        }
        for (size_t i = 0; i != bx; ++i)
        {
            int mx = block[i].x;
            int my = block[i].y;
            if ((i + 2) % 2 != 0)
                for (size_t j = 0; j != 10; ++j)
                {
                    ::StretchDIBits(pDC->GetSafeHdc(), mx, my, 1 + j, bitmapHeight, mx, my, 1 + j, bitmapHeight, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
                    Sleep(20);
                }
        }
    }
}


void CDynSplitView2::OnChuiZhiShanTiao(CDC *pDC)
{
    //block結構體用於分塊
    struct Block {
        int x, y;//記錄每一塊左上角
    };
    //重新整理螢幕
    CRect rect(0, 0, 1000, 1000);
    CBrush brush(RGB(255, 255, 255));
    pDC->FillRect(&rect, &brush);
    //獲取圖片資訊
    int bitmapHeight = dib->GetHeight();
    int bitmapWideth = dib->GetWidth();
    BYTE *bitmapData = dib->GetData();
    LPBITMAPINFO bitmapInfo = dib->GetInfo();
    //分塊,以10為單位進行分塊
    int rddy = 0;//表示X方向上是否有多餘的塊
    if (bitmapWideth % 10 != 0) rddy++;//若圖片寬度不能被10整除,則此時有多餘的塊,rddx加一
    int by = (bitmapWideth / 10) + rddy;//總塊數
    Block *block = new Block[by];//分配塊數的記憶體
    int temp = 0;//臨時變數,記錄下一塊的x的位置
    for (size_t i = 0; i != by; ++i)//以10為單位進行分塊
    {
        block[i].x = temp;
        temp += 10;
        block[i].y = 0;
    }

    if (dib->GetRGB())
    {
        CPalette *hPalette;
        hPalette = CreatBitmapPalette(dib);//建立新調色盤
        CPalette *hOldPalette = pDC->SelectPalette(hPalette, true);//選擇新調色盤,並返回老調色盤
        pDC->RealizePalette();//使選擇的調色盤生效
        for (size_t i = 0; i != by; ++i)//先將偶數塊的上半部分,奇數塊的下半部分顯示出來
        {
            int mx = block[i].x;
            int my = block[i].y;
            if ((i + 2) % 2 == 0) ::StretchDIBits(pDC->GetSafeHdc(), mx, my, 10, bitmapHeight/2, mx, bitmapHeight/2, 10, bitmapHeight/2, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            else 
                ::StretchDIBits(pDC->GetSafeHdc(), mx, bitmapHeight/2, 10, bitmapHeight / 2, mx,my, 10, bitmapHeight / 2, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
        }
        for (size_t j=0;j!=by;++j)
        {
            int mx = block[j].x;
            int my = block[j].y;
            if ((j + 2) % 2 != 0)
                for(size_t k=0;k!=10;++k)
                 ::StretchDIBits(pDC->GetSafeHdc(), mx, my, 1+k, bitmapHeight / 2, mx, bitmapHeight / 2, 1+k, bitmapHeight / 2, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            else
                for(size_t k=0;k!=10;++k)
                ::StretchDIBits(pDC->GetSafeHdc(), mx, bitmapHeight / 2, 1+k, bitmapHeight / 2, mx, my, 1+k, bitmapHeight / 2, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(50);
        }
        pDC->SelectPalette(hOldPalette, true);//調色盤還原
        ::DeletePalette(hPalette);//刪除新生成的調色盤pDC->SelectPalette(hOldPalette, true);//調色盤還原
    }
    else {
        for (size_t i = 0; i != by; ++i)//先將偶數塊的上半部分,奇數塊的下半部分顯示出來
        {
            int mx = block[i].x;
            int my = block[i].y;
            if ((i + 2) % 2 == 0) ::StretchDIBits(pDC->GetSafeHdc(), mx, my, 10, bitmapHeight / 2, mx, bitmapHeight / 2, 10, bitmapHeight / 2, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            else
                ::StretchDIBits(pDC->GetSafeHdc(), mx, bitmapHeight / 2, 10, bitmapHeight / 2, mx, my, 10, bitmapHeight / 2, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
        }
        for (size_t j = 0; j != by; ++j)
        {
            int mx = block[j].x;
            int my = block[j].y;
            if ((j + 2) % 2 != 0)
                for (size_t k = 0; k != 10; ++k)
                    ::StretchDIBits(pDC->GetSafeHdc(), mx, my, 1 + k, bitmapHeight / 2, mx, bitmapHeight / 2, 1 + k, bitmapHeight / 2, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            else
                for (size_t k = 0; k != 10; ++k)
                    ::StretchDIBits(pDC->GetSafeHdc(), mx, bitmapHeight / 2, 1 + k, bitmapHeight / 2, mx, my, 1 + k, bitmapHeight / 2, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
            Sleep(50);
        }
    }
}

void CDynSplitView2::OnBaiYeChuang(CDC *pDC)
{
    //block結構體用於分塊
    struct Block {
        int x, y;//記錄每一塊左上角
    };
    //重新整理螢幕
    CRect rect(0, 0, 1000, 1000);
    CBrush brush(RGB(255, 255, 255));
    pDC->FillRect(&rect, &brush);
    //獲取圖片資訊
    int bitmapHeight = dib->GetHeight();
    int bitmapWideth = dib->GetWidth();
    BYTE *bitmapData = dib->GetData();
    LPBITMAPINFO bitmapInfo = dib->GetInfo();
    //分塊,以10為單位進行分塊
    int rddx = 0;//表示X方向上是否有多餘的塊
    if (bitmapWideth % 10 != 0) rddx++;//若圖片寬度不能被10整除,則此時有多餘的塊,rddx加一
    int bx = (bitmapWideth / 10) + rddx;//總塊數
    Block *block = new Block[bx];//分配塊數的記憶體
    int temp = 0;//臨時變數,記錄下一塊的x的位置
    for (size_t i = 0; i != bx; ++i)//以10為單位進行分塊
    {
        block[i].x = temp;
        temp += 10;
        block[i].y = 0;
    }
    if (dib->GetRGB())
    {
        CPalette *hPalette;
        hPalette = CreatBitmapPalette(dib);//建立新調色盤
        CPalette *hOldPalette = pDC->SelectPalette(hPalette, true);//選擇新調色盤,並返回老調色盤
        pDC->RealizePalette();//使選擇的調色盤生效
        for(size_t j=0;j!=10;++j)
        for (size_t i = 0; i != bx; ++i)
        {
            
                int mx = block[i].x;
                int my = block[i].y;
                ::StretchDIBits(pDC->GetSafeHdc(),mx,my,1+j,bitmapHeight,mx,my,1+j,bitmapHeight,bitmapData,bitmapInfo,DIB_RGB_COLORS,SRCCOPY);
                Sleep(5);
        }

        pDC->SelectPalette(hOldPalette, true);//調色盤還原
        ::DeletePalette(hPalette);//刪除新生成的調色盤pDC->SelectPalette(hOldPalette, true);//調色盤還原
    }
    else
    {
        for (size_t j = 0; j != 10; ++j)
            for (size_t i = 0; i != bx; ++i)
            {

                int mx = block[i].x;
                int my = block[i].y;
                ::StretchDIBits(pDC->GetSafeHdc(), mx, my, 1 + j, bitmapHeight, mx, my, 1 + j, bitmapHeight, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
                Sleep(5);
            }
    }
}


void CDynSplitView2::OnChuiZhiBaiYeChuang(CDC *pDC)
{
    //block結構體用於分塊
    struct Block {
        int x, y;//記錄每一塊左上角
    };
    //重新整理螢幕
    CRect rect(0, 0, 1000, 1000);
    CBrush brush(RGB(255, 255, 255));
    pDC->FillRect(&rect, &brush);
    //獲取圖片資訊
    int bitmapHeight = dib->GetHeight();
    int bitmapWideth = dib->GetWidth();
    BYTE *bitmapData = dib->GetData();
    LPBITMAPINFO bitmapInfo = dib->GetInfo();
    //分塊,以10為單位進行分塊
    int rddy = 0;
    if (bitmapHeight % 10 != 0) rddy++;
    int by = (bitmapHeight / 10) + rddy;
    int my = 0;
    Block *block = new Block[by];
    for (size_t i = 0; i != by; ++i)
    {
        block[i].y = my;
        my += 10;
        block[i].x = 0;
    }
    if (dib->GetRGB())
    {
        CPalette *hPalette;
        hPalette = CreatBitmapPalette(dib);//建立新調色盤
        CPalette *hOldPalette = pDC->SelectPalette(hPalette, true);//選擇新調色盤,並返回老調色盤
        pDC->RealizePalette();//使選擇的調色盤生效
        for(size_t i=0;i!=10;++i)
            for (size_t j = 0; j != by; ++j)
            {
                int mx = block[j].x;
                int my = block[j].y;
                ::StretchDIBits(pDC->GetSafeHdc(), mx, my, bitmapWideth, 1 + i, mx, bitmapHeight-my, bitmapWideth, 1 + i, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
                Sleep(5);
            }
        pDC->SelectPalette(hOldPalette, true);//調色盤還原
        ::DeletePalette(hPalette);//刪除新生成的調色盤pDC->SelectPalette(hOldPalette, true);//調色盤還原
    }
    else {
        for (size_t i = 0; i != 10; ++i)
            for (size_t j = 0; j != by; ++j)
            {
                int mx = block[j].x;
                int my = block[j].y;
                ::StretchDIBits(pDC->GetSafeHdc(), mx, my, bitmapWideth, 1 + i, mx, bitmapHeight - my, bitmapWideth, 1 + i, bitmapData, bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
                Sleep(5);
            }
    }
}

第二部分:在MFC選單欄中呼叫這些函式

第一步,需要如第一章那樣建立一個MFC工程,並且新增好選單欄控制元件。然後,再將上面的程式碼分別寫到CDib.h和CDib.cpp中,具體如下圖所示:

第二步,在選單欄中新增相應的選項,並且設定響應函式。

第三步,新增訊息響應函式的程式碼,這裡僅僅展示一個簡單的開啟檔案並且特效顯示的程式碼,其它操作請參考MFC的相關資料,程式碼如下所示:

void CMfcimgprocDlg::On32771()
{
    // TODO: 在此新增命令處理程式程式碼
    TCHAR  szFilter[]=_T("所有*.BMP檔案|*.BMP||");
    CFileDialog fileDlg(TRUE,NULL,NULL,0,szFilter,this);
    if (IDOK == fileDlg.DoModal())
    {
        CDib dibFile;
        dibFile.LoadFile(fileDlg.GetPathName());
        if (dibFile.m_valid)
        {
            CDC *pDC = GetDC();
            CDynSplitView2 img;
            img.GetDib(&dibFile);
            img.OnDraw(pDC);
        }
    }
}

最後,顯示的效果圖片如下: