zoukankan      html  css  js  c++  java
  • DrawImage方法详解(转载)

    Image和Bitmap类概述

    GDI+的Image类封装了对BMP、GIF、JPEG、PNG、TIFF、WMF(Windows元文件)和EMF(增强WMF)图像文件的调入、格式转换以及简单处理的功能。而Bitmap是从Image类继承的一个图像类,它封装了Windows位图操作的常用功能。例如,Bitmap::SetPixel和Bitmap::GetPixel分别用来对位图进行读写像素操作,从而可以为图像的柔化和锐化处理提供一种可能。

    3.DrawImage方法

    DrawImage是GDI+的Graphics类显示图像的核心方法,它的重载函数有许多个。常用的一般重载函数有:

    Status DrawImage( Image* image, INT x, INT y);

    Status DrawImage( Image* image, const Rect& rect);

    Status DrawImage( Image* image, const Point* destPoints, INT count);

    Status DrawImage( Image* image, INT x, INT y,
                                   INT srcx, INT srcy, INT srcwidth, INT srcheight, Unit srcUnit);

    其中,(x,y)用来指定图像image显示的位置,这个位置和image图像的左上角点相对应。rect用来指定被图像填充的矩形区域, destPoints和count分别用来指定一个多边形的顶点和顶点个数。若count为3时,则表示该多边形是一个平行四边形,另一个顶点由系统自动给出。此时,destPoints中的数据依次对应于源图像的左上角、右上角和左下角的顶点坐标。srcx、srcy、srcwidth 和srcheight用来指定要显示的源图像的位置和大小,srcUnit用来指定所使用的单位,默认时使用PageUnitPixel,即用像素作为度量单位。
    调用和显示图像文件

    在GDI+中调用和显示图像文件是非常容易的,一般先通过Image或Bitmap调入一个图像文件构造一个对象,然后调用Graphics::DrawImage方法在指定位置处显示全部或部分图像。例如下面的代码:

    void CEx_GDIPlusView::OnDraw(CDC* pDC)

    {

    CEx_GDIPlusDoc* pDoc = GetDocument();

    ASSERT_VALID(pDoc);

    using namespace Gdiplus;

    Graphics graphics( pDC->m_hDC );

    Image image(L"sunflower.jpg");

    graphics.DrawImage(&image, 10,10);

    Rect rect(130, 10, image.GetWidth(), image.GetHeight());

    graphics.DrawImage(&image, rect);

    }

    结果如图7.17所示,从图中我们可以看出,两次DrawImage的结果是不同的,按理应该相同,这是怎么一回事?原来,DrawImage在不指定显示区域大小时会自动根据设备分辨率进行缩放,从而造成显示结果的不同。

    当然,也可以使用Bitmap类来调入图像文件来构造一个Bitmap对象,其结果也是一样的。例如,上述代码可改为:

    Bitmap bmp(L"sunflower.jpg");

    graphics.DrawImage(&bmp, 10,10);

    Rect rect(130, 10, bmp.GetWidth(), bmp.GetHeight());

    graphics.DrawImage(&bmp, rect);

    需要说明的是,Image还提供GetThumbnailImage的方法用来获得一个缩略图的指针,调用DrawImage后可将该缩略图显示,这在图像预览时极其有用。例如下面的代码:

    Graphics graphics( pDC->m_hDC );

    Image image(L"sunflower.jpg");

    Image* pThumbnail = image.GetThumbnailImage(50, 50, NULL, NULL);

    // 显示缩略图

    graphics.DrawImage(pThumbnail, 20, 20);

    // 使用后,不要忘记删除该缩略图指针

    delete pThumbnail;
    图像旋转和拉伸

    图像的旋转和拉伸通常是通过在DrawImage中指定destPoints参数来实现,destPoints包含对新的坐标系定义的点的数据。图7.18说明了坐标系定义的方法。

    从图中可以看出,destPoints中的第一个点是用来定义坐标原点的,第二点用来定义X轴的方法和图像X方向的大小,第三个是用来定义Y轴的方法和图像Y方向的大小。若destPoints定义的新坐标系中两轴方向不垂直,就能达到图像拉伸的效果。

    下面的代码就是图像旋转和拉伸的一个示例,其结果如图7.19所示。

    Image image(L"sunflower.jpg");

    graphics.DrawImage(&image, 10,10);

    Point points[] = { Point(0, 0), Point(image.GetWidth(), 0),

    Point(0, image.GetHeight())};

    Matrix matrix(1,0,0,1,230,10); // 定义一个单位矩阵,坐标原点在(230,10)

    matrix.Rotate(30); // 顺时针旋转30度

    matrix.Scale(0.63,0.6); // X 和 Y 方向分别乘以0.63和0.6比例因子

    matrix.TransformPoints(points, 3); // 用该矩阵转换points

    graphics.DrawImage(&image, points, 3);

    Point newpoints[] = {Point(450, 10), Point(510, 60), Point(350, 80)};

    graphics.DrawImage(&image, newpoints, 3);

    当然,对于图像旋转还可直接使用Graphics::RotateTransform来进行,例如下面的代码。但这样设置后,以后所有的绘图结果均会旋转,有时可能感觉不方便。

    Image image(L"sunflower.jpg");

    graphics.TranslateTransform(230,10); // 将原点移动到(230,10)

    graphics.RotateTransform(30); // 顺时针旋转30度

    graphics.DrawImage(&image, 0,0);
    调整插补算法的质量

    当图像进行缩放时,需要对图像像素进行插补,不同的插补算法其效果是不一样的。Graphics:: SetInterpolationMode可以让我们根据自己的需要使用不同质量效果的插补算法。当然,质量越高,其渲染时间越长。下面的代码就是使用不同质量效果的插补算法模式,其结果如图7.20所示。

    Graphics graphics( pDC->m_hDC );

    Image image(L"log.gif");

    UINT width = image.GetWidth();

    UINT height = image.GetHeight();

    // 不进行缩放

    graphics.DrawImage( &image,10,10);

    // 使用低质量的插补算法

    graphics.SetInterpolationMode(InterpolationModeNearestNeighbor);

    graphics.DrawImage( &image,

    Rect(170, 30, (INT)(0.6*width), (INT)(0.6*height)));

    // 使用中等质量的插补算法

    graphics.SetInterpolationMode(InterpolationModeHighQualityBilinear);

    graphics.DrawImage( &image,

    Rect(270, 30, (INT)(0.6*width), (INT)(0.6*height)));

    // 使用高质量的插补算法

    graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);

    graphics.DrawImage( &image,

    Rect(370, 30, (INT)(0.6*width), (INT)(0.6*height)));

    事实上,Image功能还不止这些,例如还有不同格式文件之间的转换等。但这些功能和MFC的新类CImage功能基本一样,但CImage更符合MFC程序员的编程习惯,因此下一节中我们来重点介绍CImage的使用方法和技巧。
  • 相关阅读:
    利用dockerfile定制镜像
    发布Docker 镜像到dockerhub
    Docker 停止容器
    133. Clone Graph
    132. Palindrome Partitioning II
    131. Palindrome Partitioning
    130. Surrounded Regions
    129. Sum Root to Leaf Numbers
    128. Longest Consecutive Sequence
    127. Word Ladder
  • 原文地址:https://www.cnblogs.com/zhixing/p/1986610.html
Copyright © 2011-2022 走看看