数字图像处理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);
        }
    }
}

最后,显示的效果图片如下:

猜你喜欢

转载自blog.csdn.net/qq_23557345/article/details/81900787