当前位置:C++技术网 > 精选软件 > MFC使用CImage实现图片翻转:水平镜像翻转、垂直镜像翻转和水平垂直镜像翻转

MFC使用CImage实现图片翻转:水平镜像翻转、垂直镜像翻转和水平垂直镜像翻转

更新时间:2018-12-19 15:59:04浏览次数:1+次

    首先我们使用CImage类来加载外部图像,使用很简单。声明一个对象,然后调用Load成员函数即可加载成功。代码如下:
CImage image;
image.Load(_T("E:/1.jpg"));// - 加载一幅外部图像
image.Destroy();// - 用完图片后销毁释放内存

    加载图片成功后,就是要显示图像了。然而我们要先确定图片显示在何处,所以,我们要获取显示图片的相关信息。我们使用CRect类来创建对象,用这个对象接收获取到的矩形信息。然后调用对应的窗口或者控件的获取客户区大小函数得到矩形信息。

    所以,我来获取控件(这里是Picture控件,实际的类型都是CStatic类类型)对象的指针。代码如下:
CStatic * pImgFrame = (CStatic *)GetDlgItem(IDC_PIC);

    所有静态控件都是CStatic类类型,包括Static标签、图片控件等。使用GetDlgItem函数,并传入控件的ID,即可返回控件的窗口指针,不过是CWnd父类指针,所以要做一个强制转换。

    然后通过这个控件对象指针就可以来调用GetClientRect成员函数获取客户区矩形的大小信息了。代码如下:
pImgFrame->GetClientRect(&rect);// - 获取控件客户区大小矩形

    因为要在控件上画图,贴图就是要画图的意思。所以要获取这个控件窗口上的画图的设备上下文对象指针,即调用这个控件对象的GetDC成员函数。代码如下:

CDC * pDC = pImgFrame->GetDC(); // - 获取控件的画图对象指针

    然后一切就绪,只欠东风了。要贴图,先设置一下贴图模式。因为原始图像和得到的矩形的大小可能不一样,所以要确定如何处理大小变换涉及到的像素的删减问题。这就是设置模式的原因。我们设置为COLORONCOLOR模式,可以保持比较好的效果。代码如下:

SetStretchBltMode(pDC->GetSafeHdc(), COLORONCOLOR);// - 设置拉伸图片的模式

    然后就是最后一步,贴图。调用CImage的成员函数StretchBlt来将加载的图片贴到控件上,代码如下:

image.StretchBlt(pDC->GetSafeHdc(), 0, 0, rect.Width(), rect.Height(), 0, 0, image.GetWidth(), image.GetHeight(), SRCCOPY);

    这样一来,就实现了贴图的效果。完整的代码如下:

CImage image;
image.Load(_T("E:/1.jpg"));// - 加载一幅外部图像
CStatic * pImgFrame = (CStatic *)GetDlgItem(IDC_PIC);// - 获取控件对象指针,可以是任何窗口和控件
CRect rect;
pImgFrame->GetClientRect(&rect);// - 获取控件客户区大小矩形
CDC * pDC = pImgFrame->GetDC(); // - 获取控件的画图对象指针
SetStretchBltMode(pDC->GetSafeHdc(), COLORONCOLOR);// - 设置拉伸图片的模式
image.StretchBlt(pDC->GetSafeHdc(), 0, 0, rect.Width(), rect.Height(), 0, 0, image.GetWidth(), image.GetHeight(), SRCCOPY);// - 将图像拉伸显示在控件上
image.Destroy();

效果截图如下:

    MFC使用CImage实现图片显示
    因为这里是开发经验,所以,不对具体的函数详细的解释,重在解释功能实现流程,函数使用请查阅MDSN。在C++技术网的搜索框中输入“MSDN”即可找到下载MSDN的地址和使用MSDN查阅函数的方法。
    不过,我们要实现的是旋转图片,这里才完成了最基本的显示图片。好了,我们继续。
    要实现图片的翻转,我们需要稍微了解一下StretchBlt函数。这个函数是关键。前五个参数都是确定被画的控件的画图信息,叫做画图目标的信息。
    第一个参数就是控件上的画图句柄HDC,所以我们使用画图对象来获得,代码如下:
pDC->GetSafeHdc();

    返回的类型就是HDC类型了。然后接下来指定的是画图的位置,这个位置是在控件客户区内。客户区内左上角为原点(0,0),向右为x轴正向,向下为y轴正向。确定目标是画在什么控件上就是看HDC关联的信息了。因为这个我们在前面是用控件来获取的,自然关联到的是控件。

    所以,我们就将前面得到控件的矩形的信息放进来传递进去即可。这个四个参数依次为:画图的起点的x坐标,起点的y坐标,结束的x坐标,结束的y坐标。所以我们分别设置为0,0,rect.Width(), rect.Height()。这样就是控件的左上角和右下角两个点。这两个点就确定了控件整个窗口大小。
    然后接下来的四个参数是原始图片的大小。图片也是一个矩形的,用二维矩阵存储的。坐标系也是左上角为坐标原点(0,0),向右为x轴正向,向下为y轴正向。所以指定的0,0,image.GetWidth(), image.GetHeight()就是图片的整个大小。image.GetWidth()获取图片的宽度,image.GetHeight()获取图片的高度。
    最后一个参数还是设置从图片到控件上如何贴图。设置这个参数可以实现贴图的过程中做像素运算,达到不同的效果。具体的请参考MSDN。我们使用SRCCOPY表示直接拷贝,用图片的数据直接覆盖目标位置上的像素。
    以上的解释,可以看到贴出的原理信息。而我们要实现图片翻转,我们要处理的就是目标的信息,也就是从第二个参数到第五个参数的四个,还有额外设定的信息。下面来看看。
    这里需要简要介绍一下视口。我们画图都是使用逻辑坐标系,也就是比如窗口坐标、客户区坐标。可以将这些坐标系当做一个画板。视口则是在窗口坐标系上的,决定实际画图时画图的起点从哪里开始等。我们实现图片翻转,只需要改变我们画图的起点和结束点就行了,即只需要改变视口的起始点。画图时是将图像的像素从视口起始点画到结束点。而参考的刻度和坐标系则是窗口坐标系,即画板的坐标系和刻度。如果你把视口起始点移到控件窗口矩形最下方,那么矩形内的y坐标值都是负值,如果将视口起点移到控件窗口矩形最右边,那么矩形内的x坐标就是负值。
    那么画图时,将会从视口原点向结束的点方向画,将视口原点设置成矩形最大的值,如最高和最右,那么我们将结束点指定成负数,那么就是反着画了,水平上从右往左画,就水平翻转了,垂直上从下往上画,就垂直翻转了。
    所以需要在贴图前设置下视口原点,调用画图类CDC的成员函数SetViewportOrg(视口起始点x,视口起始点y),代码如下:
pDC->SetViewportOrg(rect.Width(), 0);// - 将视口移到右上角
    然后我们画图的起始点在右上角,此时右上角为(0,0)了。然后设置画图结束的点,为负数。代码如下:
image.StretchBlt(pDC2->GetSafeHdc(), 0, 0, rect2.Width()*(-1)-1, rect2.Height(), 0, 0, image.GetWidth(), image.GetHeight(), SRCCOPY);
    目标结束点的x坐标就是负数了。对于还要减一,是让图片绘制的位置和矩形完全吻合。这样就实现了水平翻转。完整的代码如下:
CImage image;
image.Load(_T("E:/1.jpg"));// - 加载一幅外部图像
CStatic * pImgFrame = (CStatic *)GetDlgItem(IDC_PIC);// - 获取控件对象指针,可以是任何窗口和控件
CRect rect;
pImgFrame->GetClientRect(&rect);// - 获取控件客户区大小矩形
CDC * pDC = pImgFrame->GetDC(); // - 获取控件的画图对象指针
SetStretchBltMode(pDC->GetSafeHdc(), COLORONCOLOR);// - 设置拉伸图片的模式
pDC->SetViewportOrg(rect.Width(), 0);
image.StretchBlt(pDC->GetSafeHdc(), 0, 0, rect.Width()*(-1) - 1, rect.Height(), 0, 0, image.GetWidth(), image.GetHeight(), SRCCOPY);// - 将图像拉伸显示在控件上
image.Destroy();
    效果截图如下:
    图片水平镜像翻转
    类似的,可以将视口原点设置到左下角,然后调整结束的点为负数即可垂直翻转。关键两句代码不一样,其他的都一样。关键代码如下:
pDC->SetViewportOrg(0, rect.bottom);
image.StretchBlt(pDC->GetSafeHdc(), 0, 0, rect.Width(), rect.Height()*(-1) - 1, 0, 0, image.GetWidth(), image.GetHeight(), SRCCOPY);
    效果截图如下:
    图片垂直镜像翻转
    既水平翻转又垂直翻转,则设置视口起始坐标为右下角,设置结束点。关键代码如下:
pDC->SetViewportOrg(rect.Width(), rect.bottom);
image.StretchBlt(pDC->GetSafeHdc(), 0, 0, rect.Width()*(-1) - 1, rect.Height()*(-1) - 1, 0, 0, image.GetWidth(), image.GetHeight(), SRCCOPY);
    效果截图如下:
    图像水平垂直镜像翻转
    至于360度自由旋转,则比较复杂。以后研究了再分享技术经验。翻转和旋转是不一样的哦。翻转是立体上的三维空间翻转,旋转是平面的转动。