您的位置:首页 > 其它

WPF中材质制作——图片和矢量图之争

2010-03-26 14:07 423 查看
如果要做下面这样的一个东西作为背景。你会如何做呢?




1. 目标背景效果

方案一,用
PS画出来。然后把这个
PNG图片作为背景色。这个方案可以,但是如果想让这个线的颜色可配置呢?如何线的粗细不确定呢?无论哪个问题,用像素图的方式都不好
解决。

方案二,用
WPF的矢量图绘制。这个方案可以比较容易地解决上面两
个问题。

但是无论我们用哪种方式,都不会把整个图的大小画出来。而是画是一个最小的图元,然后重复。
标量图方案

对于
PS画的标量而言,有下面这样的一个图就可以了。然后在要绘制
的区域内无限重复。尤其是做网页的上的材质都是这样,要知道图片的大小可不是比文字,全部绘制出来的话图片可能会很大。而且
Visual
Designer改起来也会比较累。




2. PNG材质图片(放大后)

比如这个图叫
Twill.png,大小是
6*6。那么在
WPF中使用这个图元来建立图
1中材质的代码如下。

<

DrawingBrush

x

:

Key

="PicTwillBrush"

Stretch
="Fill"
TileMode
="Tile"

Viewport
="0,0,6,6"
ViewportUnits
="Absolute">

<

DrawingBrush.Drawing

>

<

ImageDrawing

ImageSource

="Textures/Twill.png"

Rect

="0,0,6,6"/>

</

DrawingBrush.Drawing

>

</

DrawingBrush

>

默认情况下,这个用方案一实现的材质很完美,和图
1完美一样。但是
如果用
ViewBox把这个图片放下之后会出现下面的现象。




3. 实现渲染效果(
ViewBox放大)

能看出图片已经是一块块的了。你可以把这个看作
WPF的
Bug。如果我是
QA我就会这么认为。虽然我也很理解这是平滑处理
+TitleMode渲染的结果——平滑算法没有把这个大图当成整个的一个图处理,而是单独地处理每一小块。但是我也相信这不是什么难以解决的问题。
所以它就是一个
Bug,没有什么好说的。只不过这是个小
Bug,不
Fix也就算了(因为有其它更严重的
Bug等着
MS的
Dev们),反正
有办法解决的。

一个不完全解决方案,可以使这个分块的视觉效果弱化
50.00%。
就是把图元改成这个样子。




4. 更好的
PNG材质

不一定是一块俩像素,一块
4个像素。不过两者个数之差越小越好。所
以最好是两条
3像素的线。然后视觉图会变成下面这个样子。




5. 显示效果(
ViewBox放大)

比之前要好一些。至于原因读者自己分析一下吧。(包括那个
50.00%是
如何计算出来的)

所以有经验的材质设计者,即使能用简单的角衔接,也不会用,而只使用边衔接。(当然他们主要并不是为了这个原因)

上面讨论完了位图的作法。如果你的图片不需要支持缩放,而且又不嫌
PNG占用空间大的话,用
PNG图片还是很不错的方案的。

矢量图的实现方案

有人会觉得在
WPF做个矢量图太简单了。不就是用
Expression
Design画么?对,没有错,但是问题你要画成什么个样子?因为矢量图的画法就多了。矢量的一个特点就是,图像不
再是以像素为单位的。而是一个完完整整的图形。我的第一感觉是这样的。(也许你的不是)




6. 向量材质图(根本不可行)

有人可能一眼就看出问题了,这种做法里,线的两头不是方的。多个这样的小图接起来,线看上去也不会是连续的。解决办法
和标量图的是一样的。就是使用边衔接。把图中的一条线分成两条。下面是两条做法。请读者自行判断哪种更好,并解释原因。






7. 可选向量材质图

上图的代码分别是:

<

StreamGeometry

x:Key

=

"SimpleTwill
">
M3,0 L4,0 0,4 0,3 Z M3,6 L4,6 6,4 6,3 Z</
StreamGeometry
>



<

StreamGeometry

x:Key

=

"BestTwill
">
M2.5,0 L3.5,0 0,3.5 0,2.5Z M2.5,6 L3.5,6 6,3.5
6,2.5 Z</
StreamGeometry
>

如果一开始你是用
Expression Design来画这个东
西,相信代码一定不会这么简洁的。
Expression Design最让人不能忍受的就是生成出来的
数据,常常有
1.00001这样的东西。

对应的
Brush代码是:

<

DrawingBrush

x:Key

=

"SimpleTwillBrush">

Stretch

=

"Fill
"
TileMode
=
"Tile
"

Viewport

=

"0,0,6,6
"
ViewportUnits
=
"Absolute
">

<

DrawingBrush.Drawing

>

<

GeometryDrawing

Brush

=

"Red
"
Geometry
=
"{StaticResource SimpleTwill}
"/>

</

DrawingBrush.Drawing

>

</

DrawingBrush

>

但是无论向量图自身的定义是多么的“平滑”,不幸的是它最终还是要被渲染到以像素为单位的显示器上。更不幸的是,由于
向量图的定义一般不与显示器的像素格匹配,所以在渲染的过程中,势必要做处理。结果渲染出来的就是下面这个熊样了。




8. 向量材质渲染效果

最上面一条是期望的效果,下面两条就分别是由那两个向量图元定义出来的渲染效果。如果看不清楚,下面是他们俩的放大
图。(请读者自行判断上面的结果分别是基于哪个向量图元绘制的)




9. 向量材质渲染效果(放大图)

从图中可以看出,最终的渲染结果没有对齐到像素,严格来讲就是渲染结果不正确。(顺便说一下,请不要提
SnapsToDevicePixels这个属性,如果你觉得这个属性可以解决这个问题,只说明你还没有搞清楚这个属性是在什么时候发挥作用的。其实即使我这样说了,我
感觉还是会有人回复说要用这个属性,因为他们没有认真看文章。)
关于向量图的性能问题

而且,向量没有对齐到像素的另一个严重问题就是性能。这个性能差异用肉眼就可以看得出来。如果你拖拽窗口,会发布由上
面这两个向量渲染出来的背景在闪。(此测试方法理论上只在低配置系统上可行。)为什么会闪,因为它比对齐到像素的方式至少多计算
1倍的像素点,而且每个像素点的颜色都要重新计算一遍。这个计算量是很大的。

所以很多用
WPF做过开发的人,会发现如果直接用
Design绘制出来的复杂向量图做整个程序的背景,程序就会变得很卡,如果先转成
PNG之
类的图片,再用图片做背景,性能就会好得多。原因就在于此。使用向量,每个像素点的信息都要重新计算出来。而使用图片,如果图片大小和背景大小一样,则只
需要原模原样地把图片上的像素信息搬到显示器上就行了,不需要计算什么。

但是这并不能说向量图就一定性能低下。如果能把向量图,做得与像素点能对应起来,向量图也一样可以具有很好的性能。比
如上面的向量图闪,如果我们把向量图定义成下面这个样子就不会闪了。
高性能向量图方案




10. 像素对齐的向量材质图

这个向量的定义需要更多的代码,如下所示:

<

StreamGeometry

x:Key

=

"PixelTwill
">
M0,2 L1,2 1,3 0,3 Z M1,1 L2,1 2,2 1,2 z M2,0
L3,0 3,1 2,1 Z M3,5 L4,5 4,6 3,6 Z M4,4 L5,4 5,5 4,5 Z M5,3 L6,3 6,4 5,4
Z</
StreamGeometry
>

虽然看上去代码更多了,但是由于它对齐到了像素点,所以其实性能更好。根据肉眼观测,完全看不到闪烁现象。

但是这样的向量图已经失去了向量图的意义了,向量图的一个重点特点就是无极缩放。放大之后图像依然平滑。但是这个向量
图其实就和一个标量图的效果是一样的了——放大之后就会有锯齿出现。但是如果一个向量图不会放大,用这样方式还是很不错,既提前了性能,又保证了图像的清
晰、锐利。但是这样做的成本很高,做个小图还可以,做个大图就很不现实了。
图片模糊

无论是标量图还是矢量图,实现项目中常常会出现模糊。下一篇将会为大家介绍几种常见的导致模糊的情况和解决办法。

源地址:http://www.cnblogs.com/nankezhis ...
exturesolution.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: