图像显示特效

(1)实现原理:将图像分成不同的区域小块,然后按照一定的方向、顺序先后显示在屏幕上。

(2)图像块的显示:一般使用下面这个函数进行处理

BOOL  CDC::BitBIt(int x,int y,int nWidth,int nHeight,CDC* pSrcDC,int xSrc,int ySrc,DWORD dwRop);

BitBlt的全称是 Bit Block Transfer(位块传输),专门用于将源设备上下文的一部分图像直接传送到当前设备上下文中。BitBlt函数实际完成的功能是图像的内存复制,所以效率很高。

(3)延时:图像的显示特效是通过图像的显示过程体现出来的,由于计算机处理速度太快,所以为了明星表现整个显示过程,需要加入延时函数。一个好的延时函数必须满足两个条件:一、精确延时,至少精确到毫秒级;二、延时函数与计算机的运行速度无关。延时函数如下:

void CMyEffectDisplay::DelayTime(DWORD dwMilliseconds)
{
    LARGE_INTEGER litmp;
    LONGLONG lTimeBeign;
    LONGLONG lTimeEnd;
    double dMinus;
    double dFreq;
    double dTim;

    QueryPerformanceFrequency(&litmp);    // 获得机器内部定时器的时钟频率
    dFreq = (double)litmp.QuadPart;        // 获得计数器的时钟频率
    QueryPerformanceCounter(&litmp);
    lTimeBeign = litmp.QuadPart;        // 获得时间起始值
    do
    {
        QueryPerformanceCounter(&litmp);
        lTimeEnd = litmp.QuadPart;        //获得中止值
        dMinus = (double)(lTimeEnd - lTimeBeign);
        dTim = dMinus / dFreq;            // 获得对应的时间值,单位为秒
    } while (dTim < dwMilliseconds * 0.001);
}

 

首先在CMyEffectDisplay头文件声明一些变量:

    static int s_nOffsetX;      // 图像在内存CDC中的X偏移量
    static int s_nOffsetY;      // 图像在内存CDC中的Y偏移量

    static int s_nPicWidth;     // 图像的宽度
    static int s_nPicHeight;    // 图像的高度

    static int s_nCDCWidth;     // 内存CDC的宽度
    static int s_nCDCHeight;    // 内存CDC的高度

 

然后再OnDraw函数中做一些准备工作:

   CRect rect;
    GetClientRect(rect);
    CDC memDC;
    CBitmap MemBitmap;
    memDC.CreateCompatibleDC(NULL);
    MemBitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
    memDC.SelectObject(MemBitmap);
    memDC.FillSolidRect(rect, RGB(255, 255, 255));
    Image   image(_T("E:\\素材\\jpg\\1.jpg"));
    Graphics   graph(memDC.GetSafeHdc());
    graph.DrawImage(&image, 0, 0);

    CMyEffectDisplay::s_nOffsetX = 0;
    CMyEffectDisplay::s_nOffsetY = 0;
    CMyEffectDisplay::s_nCDCWidth = rect.Width();
    CMyEffectDisplay::s_nCDCHeight = rect.Height();
    CMyEffectDisplay::s_nPicWidth = image.GetWidth();
    CMyEffectDisplay::s_nPicHeight = image.GetHeight();

  // CMyEffectDisplay::ScanDownDisplay(pDC, &memDC); // 函数调用
  ...

 

一、向下扫描特效实现

void CMyEffectDisplay::ScanDownDisplay(CDC* pDC, CDC* pMemDC)
{
    // 扫描高度
    int nHeight = min(s_nPicHeight, s_nCDCHeight);

    // 扫描宽度
    int nWidth = min(s_nPicWidth, s_nCDCWidth);

    for (int i = 0; i <= nHeight; i += 1)
    {
        pDC->BitBlt(s_nOffsetX, i + s_nOffsetY, nWidth, 1,
            pMemDC, s_nOffsetX, i + s_nOffsetY, SRCCOPY);
        DelayTime(1);
    }
}

二、垂直双重扫描特效实现

void CMyEffectDisplay::VSScanDisplay(CDC* pDC, CDC* pMemDC)
{
    // 扫描高度
    int nHeight = min(s_nPicHeight, s_nCDCHeight);

    // 扫描宽度
    int nWidth = min(s_nPicWidth, s_nCDCWidth);
    for (int i = 0; i <= nHeight / 2; i += 1)
    {
        // 向下扫描
        pDC->BitBlt(s_nOffsetX, i + s_nOffsetY, nWidth, 1, pMemDC, s_nOffsetX, i + s_nOffsetY, SRCCOPY);
        // 向上扫描
        pDC->BitBlt(s_nOffsetX, nHeight - i - 1, nWidth, 1, pMemDC, s_nOffsetX, nHeight - i - 1, SRCCOPY);
        // 延时
        DelayTime(2);
    }
}

三、向右移动特效实现:

void CMyEffectDisplay::MoveRightDisplay(CDC* pDC, CDC* pMemDC)
{
    // 扫描高度
    int nHeight = min(s_nPicHeight, s_nCDCHeight);

    for (int i = 0; i <= s_nCDCWidth - s_nOffsetX; i += 2)
    {
        pDC->BitBlt(0, s_nOffsetY, i, nHeight,
            pMemDC, s_nCDCWidth - s_nOffsetX - i, s_nOffsetY, SRCCOPY);
        DelayTime(1);
    }

    // 修正图像位置
    pDC->BitBlt(0, s_nOffsetY, s_nCDCWidth - s_nOffsetX, nHeight,
        pMemDC, 0, s_nOffsetY, SRCCOPY);
}

四、水平双重移动特效实现:

void CMyEffectDisplay::HSMoveDisplay(CDC* pDC, CDC* pMemDC)
{
    // 扫描高度
    int nHeight = min(s_nPicHeight, s_nCDCHeight);

    // 扫描宽度
    int nWidth = min(s_nPicWidth, s_nCDCWidth);

    for (int i = 0; i <= s_nCDCWidth / 2; i += 2)
    {
        // 左面部分
        pDC->BitBlt(0, s_nOffsetY, i, nHeight,
            pMemDC, nWidth / 2 - i + s_nOffsetX, s_nOffsetY, SRCCOPY);
        // 右面部分
        pDC->BitBlt(s_nCDCWidth - i, s_nOffsetY, i, nHeight,
            pMemDC, nWidth / 2 + s_nOffsetX, s_nOffsetY, SRCCOPY);
        DelayTime(1);
    }

    // 修正图像位置
    pDC->BitBlt(0, s_nOffsetY, s_nCDCWidth - s_nOffsetX, nHeight,
        pMemDC, 0, s_nOffsetY, SRCCOPY);
}

五、垂直百叶窗特效实现

void CMyEffectDisplay::VBlindDisplay(CDC* pDC, CDC* pMemDC)
{
    // 扫描高度
    int nHeight = min(s_nPicHeight, s_nCDCHeight);

    // 扫描宽度
    int nWidth = min(s_nPicWidth, s_nCDCWidth);

    // 百叶窗宽度
    int nScanLine = 8;
    for (int i = 0; i < nScanLine; i++)  // 循环8次,即分8列显示
    {
        for (int j = 0; j < nWidth; j += nScanLine)
        {
            pDC->BitBlt(j + i + s_nOffsetX, s_nOffsetY, 1, nHeight,
                pMemDC, j + i + s_nOffsetX, s_nOffsetY, SRCCOPY);
        }

        DelayTime(200);
    }
}

六、水平百叶窗特效实现

void CMyEffectDisplay::HBlindDisplay(CDC* pDC, CDC* pMemDC)
{
    // 扫描高度
    int nHeight = min(s_nPicHeight, s_nCDCHeight);

    // 扫描宽度
    int nWidth = min(s_nPicWidth, s_nCDCWidth);

    // 百叶窗宽度
    int nScanLine = 8;
    for (int i = 0; i < nScanLine; i++)
    {
        for (int j = 0; j < nHeight; j += nScanLine)
        {
            pDC->BitBlt(s_nOffsetX, j + i + s_nOffsetY, nWidth, 1,
                pMemDC, s_nOffsetX, j + i + s_nOffsetY, SRCCOPY);
        }

        DelayTime(200);
    }
}

七、垂直栅条特效实现

void CMyEffectDisplay::VRasterDisplay(CDC* pDC, CDC* pMemDC)
{
    // 扫描高度
    int nHeight = min(s_nPicHeight, s_nCDCHeight);

    // 扫描宽度
    int nWidth = min(s_nPicWidth, s_nCDCWidth);

    int nScanLine = 16;

    for (int i = 0; i <= nHeight + s_nOffsetY; i++)
    {
        for (int j = 0; j <= nWidth; j += 2 * nScanLine)
        {
            pDC->BitBlt(j + s_nOffsetX, 0, nScanLine, i,
                pMemDC, j + s_nOffsetX, nHeight + s_nOffsetY - i, SRCCOPY);

            int k = j + nScanLine;
            pDC->BitBlt(k + s_nOffsetX, nHeight + s_nOffsetY - i, nScanLine, i + s_nOffsetY,
                pMemDC, k + s_nOffsetX, 0, SRCCOPY);
        }

        DelayTime(1);
    }
}

八、水平栅条特效实现

void CMyEffectDisplay::HRasterDisplay(CDC* pDC, CDC* pMemDC)
{
    // 扫描高度
    int nHeight = min(s_nPicHeight, s_nCDCHeight);

    // 扫描宽度
    int nWidth = min(s_nPicWidth, s_nCDCWidth);

    int nScanLine = 16;

    for (int i = 0; i <= nWidth + s_nOffsetX; i++)
    {
        for (int j = 0; j <= nHeight; j += 2 * nScanLine)
        {
            pDC->BitBlt(0, j + s_nOffsetY, i, nScanLine,
                pMemDC, nWidth + s_nOffsetX - i, j + s_nOffsetY, SRCCOPY);

            int k = j + nScanLine;
            pDC->BitBlt(nWidth + s_nOffsetX - i, k + s_nOffsetY, i + s_nOffsetX, nScanLine,
                pMemDC, 0, k + s_nOffsetY, SRCCOPY);
        }

        DelayTime(1);
    }
}

九、马赛克特效实现

void CMyEffectDisplay::MosaicDisplay(CDC* pDC, CDC* pMemDC)
{
    int nTileSize = 24;    // 马赛克小方块大小
    int nRw = 0;
    int nRh = 0;

    if (s_nPicWidth % nTileSize != 0)
        nRw = 1;
    if (s_nPicHeight % nTileSize != 0)
        nRh = 1;

    // 计算小方块的个数
    int nTileCount = (s_nPicWidth / nTileSize + nRw) * (s_nPicHeight / nTileSize + nRh);

    CPtrArray    points;        // 保存所有小方块的左上坐标
    long        lx = 0;
    long        ly = 0;

    for (int k = 0; k < nTileCount; k++)
    {
        CPoint* point = new CPoint;
        point->x = lx;
        point->y = ly;
        lx = lx + nTileSize;
        if (lx >= s_nPicWidth)
        {
            lx = 0;
            ly = ly + nTileSize;
        }

        points.Add(point);
    }

    int nDelayTime = 2;
    if (s_nPicHeight * s_nPicWidth > 600 * 500)
        nDelayTime = 1;

    LARGE_INTEGER seed;
    QueryPerformanceFrequency(&seed);
    QueryPerformanceCounter(&seed);

    //初始化一个以微秒为单位的时间种子
    srand((int)seed.QuadPart);

    for (int i = nTileCount - 1; i >= 0; i--)
    {
        int n = rand() % (i + 1);
        CPoint* point = (CPoint*)points[n];

        lx = point->x;
        ly = point->y;

        pDC->BitBlt(lx + s_nOffsetX, ly + s_nOffsetY, nTileSize, nTileSize,
            pMemDC, lx + s_nOffsetX, ly + s_nOffsetY, SRCCOPY);

        /*SAFE_DELETE(point);*/
        if (point != NULL)
        {
            delete point;
            point = NULL;
        }
        points.RemoveAt(n);

        DelayTime(nDelayTime);
    }
}

十、雨滴特效实现

void CMyEffectDisplay::RaindropDisplay(CDC* pDC, CDC* pMemDC)
{
    // 扫描高度
    int nHeight = min(s_nPicHeight, s_nCDCHeight);

    // 扫描宽度
    int nWidth = min(s_nPicWidth, s_nCDCWidth);

    for (int i = 0; i <= nHeight + s_nOffsetY; i++)
    {
        for (int j = 0; j <= nHeight + s_nOffsetY - i; j++)
        {
            pDC->BitBlt(s_nOffsetX, j, nWidth, 1,
                pMemDC, s_nOffsetX, nHeight + s_nOffsetY - i, SRCCOPY);
        }

        DelayTime(1);
    }
}

 

转载于:https://www.cnblogs.com/luzuwei/p/9042186.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值