山重水复疑无路 柳暗花明又一村

--“动画截图工具”系列开发纪实

作者:马健
邮箱:stronghorse@163.net
主页:http://stronghorse.yeah.net

不知道爱美是不是真的是人的一种天性,从我开始看动画起,每次看到豪华、Q感的画面,我都会忍不住想截下来永久保存。最开始我看的动画只有VCD,当然就是直接用超级解霸进行录像,用Photoshop进行放大。但在尝试过几次后,我发现存在以下问题:

  1. 由于MPEG本身是有损压缩算法,因此一般从VCD上截取下来的画面,画质都比较差,在轮廓边缘部分容易产生碎片、毛刺,人物脸部、背景等部分则会产生色块。解霸最得意的技术之一就是它播放时的软件滤波、平滑算法,但是不知道为什么,解霸截取的图像质量比它播放出来的差太多,而且明显偏色。
  2. 壁纸通常的尺寸是800*600,大的到1024*768,而VCD的画面尺寸为352×240,也就是说,需要放大到3倍以上。Photoshop采用的放大算法似乎考虑的是速度而非质量,因此放大到2倍以内还凑合,再往上就很吃力了。而且从VCD截取的画面如果不处理直接放大的话,原画面中的碎片、毛刺等也会被同步放大,看起来会更惨。

这些问题指望靠超级解霸或Photoshop的升级来加以解决似乎不太现实,毕竟这不是他们的主打方向。因此我开始考虑开发自己的截图软件--Mpeg2Jpeg。

Mpeg2Jpeg的最初版本是基于Dongge LiIshwar K. Sethi开发的MDC库,能够逐帧解码原始VCD文件,保存成BMP或JPG。在放大方面,最早采用的是ComicsEnhancer Pro的图像处理内核,效果嘛……嘿嘿,和Photoshop差不多啦。后来在网上找到Intel公司免费发布的Intel Image Processing Library (IPL),放大效果虽然比Photoshop强,但是由于原始图片本身质量的问题,所以放大后的图像质量还是不能令人满意。

图像质量的问题曾经困扰了我很长时间,但是最终解决方案的获得却很是无心:一次我到清华去找动漫进行时老大clear,去早了他不在,我只好到清华书店去翻书杀时间。无意中在一本《数字图像处理》教材上看到用平均法去除噪声的说明,一下子茅塞顿开,冲回来后花20分钟搞定代码,运行……第一张图像一出来,我才看了一眼就激动到全身打抖!

此后没多久,最终版的Mpeg2Jpeg就在我的网站上正式发表。但是也正是在这时,先是RM、后是AVI的各种MPEG4压缩版动画片开始大行其道,Mpeg2Jpeg的作用开始减弱。

在RM刚开始流行的时候,我就开始考虑它的解码问题。但是RM文件格式一直没有公布,当时唯一能够得到的解码工具就是RealPlayer提供的ActiveX控件(SDK的发表是后来的事,而且SDK调用的解码内核也是这个控件提供的)。使用这个控件的源码可以从提供在线播放的网页上找到,也有人在CSDN上贴过在Delphi中使用这个控件的源码。但是奇怪的是,这个控件不能在VC++中直接使用,如果直接使用的话会出错。

当时我对CSDN正热衷,碰到这种倒霉事情,第一反应就是到CSDN上去问问看,结果到那里问了很长时间也没有人能够解决,一气之下干脆自己研究。最后发现RealPlayer往VC++导出的CLSID是个错误的值,因此导致控件不能使用。找到原因后剩下的事就好办了:我用三种不同的方法从RealPlayer控件往外倒源码,然后把它们凑成一个类,运行的时候用这个类动态创建RealPlayer对象就行了。这段代码就是后来我网站上放出来的RealTest,当时CSDN上有不少人下载过。

可能是RealPlayer控件用得太爽了,当需要对AVI解码的时候我第一个想到的就是Windows Media Player提供的控件,这个控件早就公开了,调用说明也很详细,相比之下比研究AVI解码要容易许多。

因为这些原因,我在Mpeg2Jpeg之后开发了MediaCam,采用控件播放RM、AVI,程序后台对播放画面取快照(即常说的“截屏”技术),软件名称中的Cam(Camera)就是从快照技术来的。因为MPEG4本身还是有损压缩,所以MediaCam中继续使用了Mpeg2Jpeg的图像平均和放大技术。

从使用的结果来看,MediaCam对RM图像的截取还算不错,原因包括:

  1. 使用RealPlayer控件的时候,虽然不能逐帧解码画面,但是通过某些技术,可以在截取画面、存盘的时候,吊住播放过程,因此漏截的画面不是太多。
  2. RM片源一般是VCD,不仅画面大小固定,而且就算截完后图像质量稍差一点,心理上也比较能够包容。

但是在截取AVI的时候就没有这种好事啦:

  1. MediaCam的界面采用的是很难缩放窗口大小的选项卡式界面,而且大小是根据RealPlayer控件的大小定的,但是一般AVI的画面大小都要比RM的大,这些画面在缩小后都会出问题。
  2. 播放过程无法控制,存盘的时候图像还在哗哗往前走,因此漏截比较多。

在认识到MediaCam的界面是造成截图质量差的最大原因后,我开始开发WMPCam,这个软件采用单纯的对话框界面,上面只有Windows Media Player控件,因此很容易随着画面的大小而改变播放窗口的大小,不会因为对画面进行压缩而影响质量。由于这个软件采用的还是截屏技术,因此软件名称还是使用了Cam后缀。

在用WMPCam截了整部《星界之纹章》后,我开始发觉对于运动比较快的画面,漏截、重复截取实在是一个不能忽视的问题。而要真正解决漏截问题,唯一的办法是回到老路上来--掌握AVI解码技术,逐帧解码AVI画面。因此只好又收拾起精神,彻底抛弃控件,回头考虑怎么对AVI文件解码的问题。

能对AVI文件进行解码的源代码例子不少,我在DOOM9上就找到了VirtualDub、NanDub等的源代码。VirtualDub和NanDub在视频解码方面是一样的,但是文件实在太多,尤其是那一堆ASM文件,实在不是玩的。

就在我犹豫是否下定决心通读NanDub源代码的时候,偶然间在CSDN上看到一篇文章,才突然想起一个一直被我忽略了的问题--AVI其实是标准VFW格式,而对VFW格式微软已经提供足够详细的接口了。至此所有问题迎刃而解:在MSDN上随便搜一下,例子一大把,别说解码AVI,编辑、压缩都够了。

托这些例子的福,我开发出了Avi2Jpeg,在功能上和界面上还参考了NanDub和Mpeg2Jpeg。也就是说,既能连续或跳跃截图,又能用图像平均和高精度放大技术获得高质量的大图片。

因为Avi2Jpeg是直接从AVI媒体流中解码图像帧,没有采用截屏技术,因此不仅不存在漏截的问题,而且运行的时候也不需要设置屏幕显示颜色,或保持播放窗口可见,另外软件也可以不用Cam这个后缀了。从实际使用情况来看,效果比WMPCam要好。

附录:“动画截图工具”系列的选用

源文件 工具 技术 说明
VCD Mpeg2Jpeg 解码  
AVI(包括标准非压缩AVI、DivX、XDiv) Avi2Jpeg 解码 使用前请先安装相应解码器,保证Windows Media Player能够正常播放
RM MediaCam 截屏 使用前请先安装RealPlayer。如果万一WMP图像截取失败,即截出来的图片一片黑,可以在Windows的“开始”菜单中点“运行”,运行程序dxdiag.exe后,在“显示”页中点“禁用”DirectShow硬件加速。截完后再启动硬件加速即可。
ASF等其它MPEG4文件 WMPCam 截屏 使用前请先安装相应插件,保证Windows Media Player能够正常播放。如果万一图像截取失败,即截出来的图片一片黑,可以在Windows的“开始”菜单中点“运行”,运行程序dxdiag.exe后,在“显示”页中点“禁用”DirectShow硬件加速。截完后再启动硬件加速即可。 

源文件如果是DVD的话,过程有点麻烦:

  1. 先将DVD复制到硬盘,约需10分钟。
  2. 用DVD2AVI生成d2v项目文件,一张D5约需5分钟。
  3. 用VFAPI转成AVI,约需数秒。

这个时候就可以用Avi2Jpeg了。如果你做过DVDrip,上面的过程当然一看就懂。如果看不懂……你还是先去找一份图文并茂的《DVDrip制作攻略》之类的文章看看吧。

不过我不推荐用Avi2Jpeg截DVD,理由如下:

  1. Avi2Jpeg没有缩放功能,在截DVD画面的时候会变形,16:9的时候尤其明显。
  2. Avi2Jpeg没有切边功能,截出的画面可能会有黑边。

其实对于高手来说,在压缩DVDrip的时候,由于采用某些技术手段,压缩出来的画面质量会比原DVD还好,所以我觉得最好还是压成DVDrip后再截。