WPF and Silverlight 学习笔记(二十七):基本图形的使用(2)Path和位图操作
在上一篇文章中主要讨论的是除Path之外的基本图形,本文主要讨论使用Path创建更加复杂的图形以及位图的处理。
一、使用Path构建复杂图形
Path所构建的图形由Data属性来定义,其属性的类型为Geometry(几何类),几何类类型的继承关系请参考我上一篇文章。例如要创建一个100*30的矩形,可以有两种做法:
1: <StackPanel>
2: <!--使用Rectangle直接创建矩形图形-->
3: <Rectangle Fill="Red" Width="100" Height="30" HorizontalAlignment="Left" />
4: <!--使用Path创建矩形图形-->
5: <Path Fill="Blue">
6: <Path.Data>
7: <RectangleGeometry Rect="0,0,100,30" />
8: </Path.Data>
9: </Path>
10: </StackPanel>
从上面的代码来看,如果创建单一的图形,使用相应的图形类更简单,但是通过Path可以构建更加复杂的图形,例如想创建一个圆环,一种做法是使用两个圆形构建,另一种做法就是例如Path,可以直接绘制出圆环:
1: <Grid>
2: <Grid.RowDefinitions>
3: <RowDefinition />
4: <RowDefinition />
5: </Grid.RowDefinitions>
6: <!--使用两个圆形叠加出圆环,但要受到其所有容器的限制-->
7: <Canvas Grid.Row="0">
8: <Ellipse Fill="Red" Canvas.Left="10" Canvas.Top="10"
9: Width="100" Height="100" />
10: <Ellipse Fill="White" Canvas.Left="35" Canvas.Top="35"
11: Width="50" Height="50" />
12: </Canvas>
13: <!--直接使用Path构建圆环-->
14: <Canvas Grid.Row="1">
15: <Path Fill="Red">
16: <Path.Data>
17: <GeometryGroup>
18: <!--Center为圆心的坐标,RadiusX、RadiusY分别为X、Y两轴的半径-->
19: <EllipseGeometry RadiusX="50" RadiusY="50"
20: Center="60,60" />
21: <EllipseGeometry RadiusX="25" RadiusY="25"
22: Center="60,60" />
23: </GeometryGroup>
24: </Path.Data>
25: </Path>
26: </Canvas>
27: </Grid>
另外,由于第一种做法是一种“虚假”的圆环,所以,当给两个圆环所在的Canvas添加背景时,第一种做法的圆环不能出现“镂空”的效果,例如为两个Canvas添加如下的背景图片:
1: <Canvas.Background>
2: <ImageBrush ImageSource="Images/Logo.png" Stretch="Uniform" />
3: </Canvas.Background>
效果为:
此外Path还可以构建很多更复杂的图形,在这里就不一一列举了,请感兴趣的朋友自行尝试。
二、位图操作
WPF支持以下格式的位图:BMP、JPEG、PNG、TIFF、Windows Media Photo、GIF和ICO。在System.Windows.Media.Imaging命名空间定义了一系列处理图像文件的类型,其中最常使用的是Image类处理位图。
使用Image类型的Source属性加载图片,Source属性的类型是ImageSource类型。ImageSource有两个子类DrawingImage和BitmapSource,分别用来处理不依赖分辨率的图画对象和依赖分辨率的图画对象(位图)。其继承关系如下图所示:
1、使用BitmapImage加载图片
BitmapImage类型是Image类型Source属性默认的类型,它用来加载已存在的图片,这个图片可以是存放在网络上的,也可以是本地或项目资源中的图片,例如:
1: <StackPanel Orientation="Horizontal">
2: <!--使用绝对URL定位网络上的图片-->
3: <Image Source="http://www.cnblogs.com/images/logo.gif"
4: Margin="10"/>
5: <!--使用绝对URL定位本地计算机上的图片-->
6: <Image Source="D:\Pictures\mct.gif"
7: Margin="10"/>
8: <!--使用相对URL定位到项目中的资源图片-->
9: <Image Source="Images/Logo.png"
10: Margin="10"/>
11: </StackPanel>
2、使用RenderTargetBitmap创建图片
使用RenderTargetBitmap可以自定义任意一个Visual类型的子类,将其作为图片的内容,创建一个ImageSource,供界面显示,例如创建一个红色的五角星:
XAML代码如下:
1: <Window x:Class="WPF_27.Window4"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: Title="Window4" Height="250" Width="250">
5: <Canvas Background="Yellow" Width="200" Height="200">
6: <Image x:Name="img" Stretch="None"/>
7: </Canvas>
8: </Window>
在后台的代码中:
1: private void DrawImage()
2: {
3: // 创建一个RenderTargetBitmap对象
4: RenderTargetBitmap bmp = new RenderTargetBitmap(
5: 200, 200, // 设置图片的大小(单位为像素)
6: 96, 96, // 设置图片的水平及竖直分辨率
7: //(注间此处应与系统定义的DPI相同,否则会出现图形异常)
8: PixelFormats.Pbgra32); // 图片的格式
9:
10: // 定义五角星的五个顶点
11: Point p1 = new Point(
12: 100 + 100 * Math.Sin(0),
13: 100 - 100 * Math.Cos(0));
14: Point p2 = new Point(
15: 100 + 100 * Math.Sin(2 * Math.PI / 5),
16: 100 - 100 * Math.Cos(2 * Math.PI / 5));
17: Point p3 = new Point(
18: 100 + 100 * Math.Sin(2 * Math.PI * 2 / 5),
19: 100 - 100 * Math.Cos(2 * Math.PI * 2 / 5));
20: Point p4 = new Point(
21: 100 + 100 * Math.Sin(2 * Math.PI * 3 / 5),
22: 100 - 100 * Math.Cos(2 * Math.PI * 3 / 5));
23: Point p5 = new Point(
24: 100 + 100 * Math.Sin(2 * Math.PI * 4 / 5),
25: 100 - 100 * Math.Cos(2 * Math.PI * 4 / 5));
26:
27:
28: // 定义红色的五角星
29: Polygon p = new Polygon();
30: p.Fill = new SolidColorBrush(Colors.Red);
31: p.FillRule = FillRule.Nonzero;
32:
33: p.Points.Add(p1);
34: p.Points.Add(p3);
35: p.Points.Add(p5);
36: p.Points.Add(p2);
37: p.Points.Add(p4);
38:
39: // 定义圆
40: Ellipse e = new Ellipse();
41: e.Stroke = new SolidColorBrush(Colors.Red);
42: e.Width = 200;
43: e.Height = 200;
44:
45: Canvas.SetLeft(p,0);
46: Canvas.SetTop(p,0);
47: Canvas.SetLeft(e,0);
48: Canvas.SetTop(e,0);
49:
50: // 定义承载两个图形的Canvas对象
51: Canvas c = new Canvas();
52: c.Background = new SolidColorBrush(Colors.Yellow);
53: c.Children.Add(e);
54: c.Children.Add(p);
55:
56: // 处理其显示的大小及位置
57: c.Measure(new Size(200, 200));
58: c.Arrange(new Rect(0, 0, 200, 200));
59:
60: // 生成图片并显示
61: bmp.Render(c);
62: img.Source = bmp;
63: }
执行之后的效果如下图所示:
在此处要注意显示器的像素和分辨率的关系,有关两者间的关系,园子中有一篇文章写的比较清楚,大家可以参考:
http://www.cnblogs.com/helloj2ee/archive/2009/04/21/1440709.html
3、为图片添加水印
例如,对上节第二张图片加水印,可以使用如下代码:
1: private void ShowPicture()
2: {
3: BitmapImage source = new BitmapImage();
4: source.BeginInit();
5: // 获取网络上的一张图片
6: source.UriSource =
7: new Uri(
8: "http://images.cnblogs.com/cnblogs_com/DragonInSea/" +
9: "WindowsLiveWriter/WPFandSilverlight1_B8D5/26-2_6.png");
10:
11: // 当图片下载完成后,对源图片加水印
12: source.DownloadCompleted += delegate
13: {
14: // 源图片
15: Image backImage = new Image();
16: backImage.Source = source;
17:
18: // 水印
19: TextBlock water = new TextBlock();
20: water.Text = "Dragon In Sea";
21: water.FontSize = 24;
22: water.FontFamily = new FontFamily("Consolas");
23: water.Background = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0));
24: water.Foreground = Brushes.Gold;
25:
26: Canvas.SetLeft(backImage,0);
27: Canvas.SetTop(backImage,0);
28:
29: Canvas.SetLeft(water, source.Width - 200);
30: Canvas.SetTop(water,source.Height-50);
31:
32: // 将源图片与水印添加到同一个Canvas容器中
33: Canvas canvas = new Canvas();
34: canvas.Children.Add(backImage);
35: canvas.Children.Add(water);
36:
37: canvas.Measure(new Size(source.Width, source.Height));
38: canvas.Arrange(new Rect(0, 0, source.Width, source.Height));
39:
40: // 显示全成后的图片
41: RenderTargetBitmap newImage = new RenderTargetBitmap(
42: (int)source.Width, (int)source.Height,
43: source.DpiX, source.DpiY,
44: PixelFormats.Pbgra32);
45: newImage.Render(canvas);
46:
47: img.Source = newImage;
48: };
49:
50: source.EndInit();
51: }
执行的结果如下图所示:
用此方法,不更改源图片,显示出来的是合成后的图片。
下一篇,我们将继续讨论对于图片的操作。