在前文 SharpDX之Direct2D教程II——加载位图文件和保存位图文件 中,发现在VB2010中不能很好的运用SharpDx中的WIC组件进行图片的编码工作。可能是我的设置问题,也可能是SharpDx对VB2010支持的不够好(用C#就没有问题) ,有网友将代码贴到VB2012中,也发现可以运行的很好。由于手头上没有VS2012,故这个功能的实验放置一段时间

不过,回过头想一想。我们需要WIC的图片编码功能么?

Direct2D(SharpDx等)的显示绘制优势

和GDI、GDI+相比,Direct2D(SharpDx等)的优势在于利用硬件(GPU)绘制,节省时间,节省CPU的占用率,提高绘制效率。

GDI、GDI+等的绘制流程如下:

1、GDI、GDI+将绘制命令传到CPU

2、CPU开始在内存中绘制图形

3、CPU将绘制完的图形传到GPU

4、GPU将图形传到显示设备(显示器等)

Direct2D(SharpDx等)的绘制模式有Hardware(基于硬件)、Software(基于软件)、Default(默认)

其中Software模式和GDI、GDI+绘制流程一样。Default模式在初始化的时候会进行硬件检测,如果硬件支持,则采用Hardware模式,如果硬件不支持,则采用Software模式

Direct2D(SharpDx等)在模式选择为Hardware时的绘制流程如下:

1、Direct2D(SharpDx等)将绘制命令传到CPU

2、CPU将绘制命令传到GPU

3、GPU在显存中绘制图形

4、GPU将绘制好的图形传到显示设备(显示器等)

上述两个流程的区别在于:

GDI、GDI+等是利用CPU绘制图形,绘制图形在内存中有备份。

Direct2D(SharpDx等)的Hardware模式是利用GPU绘制图形,内存中并没有备份。和GDI、GDI+等相比优势在于快,节省CPU占用(GPU的绘制效率远高于CPU)。但也有一些问题,就是CPU将绘制命令传到GPU后,就不管了,至于GPU绘制成什么样子,那就是GPU的事了。这也可以解释为何早期的显卡,有时会出现渲染的错误。

WIC如何将绘制的图形编码到图形文件

在Direct2D的说明帮助里提到,如果需要利用WIC将RenderTarget上的内容编码到图形文件中的话,则得把RenderTarget的模式设置为Software(不能是Hardware,以目前的电脑配置Default基本上等同于Hardware)

WIC将RenderTarget上的内容编码到图形文件的流程如下:

1、创建WicBitmap对象,再之上创建WicRenderTarget对象

2、创建D2DBitmap对象,再利用CopyFromRenderTarget方法把RenderTarget上的内容复制到D2DBitmap对象

3、利用WicRenderTarget对象的DrawBitmap方法把D2DBitmap对象绘制到WicBitmap对象上

4、创建BitmapEncoder对象,在之上创建BitmapFrameEncoder对象,并创建和BitmapEncoder相关的Stream对象

5、将WicBitmap对象写入到BitmapFrameEncoder对象

6,调用BitmapFrameEncoder对象和BitmapEncoder对象的Commit方法,将内容编码到Stream对象,可以保存到文件

在Software模式下,是利用CPU绘制图形,结果在内存中有缓存。WIC的WicRenderTarget对象的DrawBitmap方法能把缓存中的内容绘制到WicBitmap上。

而在Hardware模式下,利用的是GPU绘制图形,在内存中没有缓存。WIC的WicRenderTarget对象的DrawBitmap方法没法把内容绘制到WicBitmap上(因为缓存中没有),强行调用的话,会报错的。

我们需要WIC的图片编码功能么?

用Direct2D(SharpDx等)就是看重其硬件加速的能力,但也籍此不能使用WIC保存绘制的内容;如果要使用WIC保存绘制的内容,则Direct2D(SharpDx等)的绘制模式设置为Software,但又牺牲了硬件加速能力,其效率和GDI、GDI+等相差无几。

再加上WIC实际上是调用系统默认的编码器对图形进行编码,但同时几乎不提供的可调参数的功能。例如:我们知道在保存JPG的时候,可以设置精度(因为JPG是有损压缩,根据精度的不同,保存的文件大小也不相同),但是用WIC保存为JPG的时候,却没有参数可以设置精度(或者是我没找到);保存为GIF时,可以设置每帧之间的间隔时间,但在WIC中也没有相应的属性可以提供(也许可以通过添加MetaData的方式设置该属性)。

换个角度考虑,图形的编码远比解码复杂的多。解码图形,只要依据已经存在的数据按照一定的规则解码就行了,即使是用不同的解码器解码出来的图形应该是毫无二致。但是,编码就不同了,同样的格式、同样的参数,不同的编码器出来的文件可能就不一样了(我们用PS和Fireworks编码出来的GIF文件大小就不一样)。

因此,如果是采用默认编码器对图形编码的话,真不一定需要WIC(WIC仅仅是提供了一个调用的途径),在GDI+中完全可以利用Bitmap对象的Save方法做到。如果需要对编码进行参数设置的话,以获得不同的文件的话,这个似乎WIC又做不到。

因此,看来我们并不需要WIC的图片编码功能。再说,我们使用Direct2D(SharpDx等)是依靠其硬件加速的能力,加强图形渲染功能。

现在在研究GIF的编码,发现 Robin 写的系列文章不错。待研究后再书新文

04-14 02:35