65.9K
CodeProject 正在变化。 阅读更多。
Home

在 GDI+ 中应用矩阵变换

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2014 年 6 月 20 日

CPOL

2分钟阅读

viewsIcon

12482

使用 GDI+ 实现 PowerPoint 等应用中的“将图片填充到形状”选项的步骤。

引言

在开发一个使用 GDI+ 绘制高级图形的应用程序时,我遇到了一个需求,即绘制椭圆、正方形、三角形、箭头等形状,并用用户选择的图像填充它们。

背景

此功能类似于 Microsoft PowerPoint 中提供的两种选项:

  1. 将图片平铺为纹理: 在此选项中,用户选择的图像在形状内部平铺。

  2. 将图片填充到形状: 在此选项中,用户选择的图像在形状内部绘制,使图像在形状上正确展开。即使增加或减小形状的大小,也不会发生平铺。

在这篇博文中,我们将深入探讨 “将图片填充到形状”选项,因为当使用图像纹理画笔填充任何形状时,这种模式会带来典型的挑战。

Windows GDI+ 提供了创建纹理画笔(WrapModeClamp 选项)并将其用于在用户选择的形状内部绘制的设施。

实现“将图片填充到形状”选项的步骤

  1. 加载要填充到形状内部的图像
    Image image(L"C:\\Users\\Public\\Pictures\\Sample Pictures\\Tulips.jpg");
    Image* ptrImagePoly = (Image*)&bmpInMemoryPoly;
    Graphics graphicsInMemoryPoly(ptrImagePoly );
  2. 在创建纹理画笔时,指定画笔的图像
    TextureBrush tBrushPoly(ptrImagePoly );
  3. 然后在纹理画笔中指定 WrapMode Clamp(适应形状)
    tBrushPoly.SetWrapMode( WrapModeClamp );
  4. 创建矩阵对象并设置适当的相对平移(请参阅下面的代码列表 2 和 3)
    Matrix X1;
    X1.Translate( 247, 100 );
  5. 将矩阵平移设置为纹理画笔,以便画笔在正确的位置绘制图像。如果未执行此操作,则画笔默认在 0, 0 位置绘制图像,并且图像将无法正确填充到形状中。
    // Set the translation to the image brush rect 
    tBrushPoly.MultiplyTransform(&X1);

代码列表 1:用于绘制任何注释的基本 GDI 代码设置

CPaintDC dc(this);
 
Graphics graphics(dc.m_hDC);
Image image(L"C:\\Users\\Public\\Pictures\\Sample Pictures\\Tulips.jpg");
 
Pen blackPen(Color(255, 255, 0, 0));
graphics.SetInterpolationMode( InterpolationModeHighQuality );

代码列表 2:绘制一个正方形并用图像填充它

Bitmap bmpInMemoryRect( 200, 200 );
 
Image* ptrRect = (Image*)&bmpInMemoryRect;
Graphics graphicsInMemoryRect( ptrRect );
 
 
// Set translation according to the top-left tip of the Square shape.
// This moves the origin to 20, 20.
 
Matrix X2;
X2.Translate( 20, 20 );
 
graphicsInMemoryRect.DrawImage( &image, 0, 0, 200, 200 );
TextureBrush tBrushRect( ptrRect );
 
 
// Set the translation to the image brush rect
tBrushRect.MultiplyTransform(&X2,MatrixOrderAppend); 
tBrushRect.SetWrapMode( WrapModeClamp );
 
graphics.DrawRectangle( &blackPen, Rect(20, 20, 200, 200) ); 
graphics.FillRectangle( &tBrushRect, Rect(20, 20, 200, 200) );

代码列表 3:绘制一个箭头并用图像填充它

Point * points; 
int iPointCount = 7; 
points = new Point[iPointCount]; 
 
// point[6]
// /\
// point[5] / \ point[0]
// - - 
// point[4] || point[3]
// point[4] ||
// point[2] -- point[1]
 
 
points[0].X = (int)406.78; 
points[0].Y = (int)220.11; 
 
points[1].X = (int)367.04; 
points[1].Y = (int)220.11; 

points[2].X = (int)367.04; 
points[2].Y = (int)321.66;
 
points[3].X = (int)287.57;
points[3].Y = (int)321.66; 

points[4].X = (int)287.57; 
points[4].Y = (int)220.11;
 
points[5].X = (int)247.83; 
points[5].Y = (int)220.11; 
 
points[6].X = (int)327.31; 
points[6].Y = (int)100.65;
 
 
Bitmap bmpInMemoryPoly( 160, 222); 
Image* ptrImagePoly = (Image*)&bmpInMemoryPoly; 
Graphics graphicsInMemoryPoly(ptrImagePoly );
 

// Set translation according to the Left Most 'X' point and the Top Most 'Y' point of the arrow
Matrix X1;
X1.Translate( 247, 100 );
 
graphicsInMemoryPoly.DrawImage( &image, 0, 0, 160, 222 );
 
TextureBrush tBrushPoly(ptrImagePoly );
tBrushPoly.SetWrapMode( WrapModeClamp );
 
 
// Set the translation to the image brush rect
tBrushPoly.MultiplyTransform(&X1);

graphics.DrawPolygon( &blackPen, points, iPointCount );
graphics.FillPolygon( &tBrushPoly, points, iPointCount );

delete [] points
© . All rights reserved.