📄 comicenhancer pro.htm
字号:
<P>如果调用Render时使用的是自己创建的内存DC,显示完后在内存DC中就生成了一幅DDB(device dependent
bitmap,设备相关位图),理论上讲这时候就可以进行图像处理了,但实际上还存在问题:
<OL>
<LI>对DDB的象素进行操作保证慢得让你想跳楼,只能再通过API调用将DDB转换为DIB(device independent
bitmap,设备无关位图)才能忍受,即在内存中同时有两份内存拷贝,增加无谓的内存消耗。
<LI>内存DC、DDB均是与当前显示设备相兼容的,其所能表示的颜色数、内存消耗也与当前显示设置相关,如果当前显示器设定为256色,则原来24位真彩的JPG载入后也缩水成256色;如果当前显示器设置为32位色,虽然颜色不会缩水,但内存消耗又上去了(约为16位色的3倍)。而且谁知道用户运行程序的时候显示器会设成什么样?
<LI>DDB转DIB除消耗内存外,还需要消耗时间,图像尺寸大、颜色设置高时更明显。 </LI></OL>
<P>由于以上种种原因,我虽然开始时采用了OleLoadPicture+Render的方法,但最后还是放弃了。</P>
<P>Windows
API虽然提供了图像解码功能,但是没有提供图像编码功能,因此在存盘的时候,一般还需要第三方工具的支持,不然就需要苦读《图像格式大全》,再熬夜写代码了。对于JPG格式,现在最有名也最流行的第三方工具有IJG和IJL两个。</P>
<P><FONT color=#ff0000><A name="三、IJG vs. IJL">三、IJG vs. IJL</A></FONT></P>
<P>IJG的全称是<A href="http://www.ijg.org/">Independent JPEG
Group</A>(独立JPEG小组),该组织以<A
href="ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/">C语言源代码</A>的形式提供应用广泛、完全免费的JPEG解码/编码函数库,编译后生成二进制格式的LIB文件,可以连接到其他编译型语言的程序中。其实对于Windows程序员来说,这个函数库最难的地方就是对编译选项的设置(Unix无此问题),一旦设置完成,编译成功,差不多就可以卖钱了。有些开发商就是将对IJG的调用封装一下,生成DLL或OCX,就开始堂而皇之地收费了。由于IJG生成的代码简洁干净,无需任何DLL或OCX,很多收费的图像浏览器、编辑器等也直接或间接地基于IJG。另外在IJG的源代码中还包含对GIF、BMP、PPM、TGA、RLE文件解码/编码的实例代码,因此也有人说IJG提供的JPEG库支持这些图像格式,其实这些代码仅供IJG测试用,一般生成的LIB文件中并不包括这部分代码,如果想支持这些格式还需要在此源码基础上花功夫。</P>
<P>IJG的全称是<A
href="http://developer.intel.com/software/products/perflib/ijl/">Intel® JPEG
Library</A>,是由Intel公司以DLL的形式免费提供的JPG解码/编码库。其实它的内核就是IJG,只不过专门针对Intel架构(主要是MMX)进行了彻底的优化,因此在Wintel环境下速度一流。这个工具最大的特点就是简单,一共只有六个函数(ijlInit、ijlFree、ijlRead、ijlWrite、ijlGetLibVersion、ijlErrorStr),而且随机文档中附有完整的VC++实例(用VB和Delphi的家伙们去哭吧),因此对于VC程序员来说不用费什么脑子就可以对JPEG应用自如。另外这个工具还有一个很独特的地方:不论读的是什么格式的JPG文件,读完后都被转成了24位真彩,存盘时也只能存为24位真彩。</P>
<P>在开始的时候,我考虑的是IJG,虽然方便,但是到哪都需要带一个ijl15.dll,和我一贯主张的“绿色软件”的理念相抵触,因此越看越不顺眼;最要命的是它只能存为24位真彩色的JPG,这对于黑白漫画来说实在是太浪费了。因此我最后还是痛下决心,再接再厉,终于找到了一个VC++的编译设置,成功编译了IJG,所以才有现在这个应用。唉,我的网费……。</P>
<P><FONT color=#ff0000><A name="四、ComicEnhancer vs. Photoshop">四、ComicEnhancer
vs. Photoshop</A></FONT></P>
<P>其实我个人认为,Photoshop的漫画增强效果还是不错的,但在分享转换参数方面还存在一些不足,所以我才会编这个程序。
<OL>
<LI>从总体上说,ComicEnhancer模仿的是Photoshop的Batch
Action功能,但支持的图像格式、图像处理方法和效果、效率均比Photoshop差一点,毕竟是在业余时间里赶出来的东西。
<LI>Batch
Action看得见的参数不多,建立时一般是对图像操作进行录制,因此如果在BBS上撒个帖子:“我用Photoshop进行了××操作,增强了××漫画”,别人大概也是有听没有用。而ComicEnhancer的所有参数均是可见的,结果也是可重复的,因此如果在BBS上撒个帖子:“我用ComicEnhancer增强了××漫画,所用参数为××”,大家都可以受益。
<LI>Photoshop里我最欣赏的就是Curve功能,通过用样条函数表示的非线性映射,能够同时调整图像的亮度和对比度。但是这个功能的可重复性实在是太小。ComicEnhancer的亮度调整、对比度调整、高亮区调整合起来,马马虎虎也够用了,而且是可重复的。
<LI>最要命的一点,Photoshop实在是太大、太全了,会用它处理漫画的人好象不太多,而且自从开始收集电子版漫画后,我对Photoshop所占据的100多兆一直耿耿于怀。
</LI></OL>
<P><A name="JPEG,BMP,GIF and PNG"><FONT color=#ff0000>五、JPEG,BMP,GIF and
PNG</FONT></A></P>
<P>如果说JPEG是当今网上最流行的图像格式,大概不会有人反对。但是由于JPEG本身是一种有损压缩格式,在提供最小文件长度的同时,JPEG格式也具有以下缺点:</P>
<OL>
<LI>JPEG主要针对的是“自然图像”,即色彩比较丰富、颜色过渡比较自然的图像,如普通照片等。而动画、漫画一般是“非自然图像”,即颜色跳跃比较大,并且有文字等信息,这样在线条、文字等边缘部分就会产生细小的碎片(高频噪声),在压缩比比较大时尤其明显。这对狂热追求画质一族来说实在是个遗憾。
<LI>虽然某些人宣称“JPEG还原时无失真”,但这不过是一句“无知者无畏”的广告用语罢了。由于JPEG的有损压缩特性,实际上每压缩一次,都会损失一些图像信息,因此JPEG并不适合保存图像处理的中间结果。如果对以JPEG格式发行的图片进行编辑,再保存成JPEG格式,也是每保存一次都会造成损失。
</LI></OL>
<P>由于这些原因,网上有人开始尝试用无损压缩格式保存动漫图片。常见的无损压缩格式有BMP、GIF和PNG等:</P>
<P>1、BMP<BR>BMP格式的特点是操作简单,基本上所有的工具都支持它(Photoshop之流不支持16位色BMP),如果想自己开发图像处理程序的话,读/写BMP文件的源代码也随处可见。但是BMP图像基本上是把象素信息直接写到文件里,不进行压缩,因此用BMP格式保存的图像文件一般都比其它格式的文件大得多,导致几乎没有谁会在网上发行BMP格式的动漫图片。我唯一见过的一次是有人以单色BMP格式发行了一套赤松健的《永远的圣诞老人》,长度比压缩比65%的256级灰度JEPG还小,不过单色BMP不是黑就是白,没有任何过渡,看起来实在是……</P>
<P>2、GIF<BR>GIF大概称得上是目前网上最流行的无损压缩图像格式。我看到的第一套以GIF格式发行的漫画是英文版《乱马》,其图像之细腻绝对不是JPEG能够比拟的,而且由于采用16级灰度,图像尺寸也不大。支持16级灰度GIF格式的软件并不多,估计是用ACDSEE的Photo
Enhancer(现在叫Foto
Canvas)一张一张转出来的。后来陆续又见过一些以GIF格式发行的港版漫画,虽然图像都不错,不过文件尺寸上就差远了--全是256色GIF,估计都是用ACDSEE批量转出来的。不过GIF也有一些问题:</P>
<OL>
<LI>GIF压缩算法的核心--Lempel-Ziv-Welch
(LZW)算法是有版权的,版权归Unisys公司所有。开发解码程序也就算了,如果开发编码程序,就算开发的是freeware,也需要缴纳版权费,否则是违法行为。
<LI>GIF表现灰度和调色板图像还不错,表现24位真彩图像的时候,效果不是很理想。ACDSEE在把其它格式的图像批量转成GIF的时候,干脆就把所有彩色图像都转成256级调色板GIF。
</LI></OL>
<P>有鉴于此,至少我是不会在我开发的软件里支持GIF编码的,解码部分调用的也是微软提供的Windows API。</P>
<P>3、PNG<BR>对于CompuServe向支持GIF格式的freeware收费的行为,网络界当然不会没有反对的声音。其中一些反对者聚集起来,提出了新的PNG格式(听起来象不象DivX和Xvid的故事?)。PNG的压缩算法采用公开的ZIP压缩算法,不仅压缩率比LZW高,而且不需要支付版权费用,连压缩、解压源代码都有专门的zlib组织免费提供。<BR>与GIF相比,PNG格式不仅文件长度更小,而且在色彩方面支持得更好,差不多达到BMP的水平。尤其是动漫图片常用的24位真彩和256级、16级、8级和4集灰度。</P>
<P>因此,整个“动漫DIY系列”将全面支持PNG格式。</P>
<P><A name="bilinear,bicubic and nearest"><FONT color=#ff0000>六、bilinear,bicubic
and nearest</FONT></A></P>
<P>图像放大历来是个让人头疼的问题,原因就在于原集与相集的一对多关系。即在分辨率不变的情况下,原图像上的一个点放大后,将成为新图像上的多个点。这些点如果与原图像上的点颜色完全相同(即nearest算法),则图像会出现明显的锯齿,所以好的放大算法一般是按照某种公式计算新图像上每一个点的颜色,使新图像上的点与周围点的颜色过渡平滑一些、自然一些,以消除锯齿。</P>
<P>这种计算公式通常采用插值公式,而常用的插值公式有线性(linear)插值、三次(cubic)插值等。由于2D图像的插值需要沿x、y两个方向进行,因此加上代表“双向”一词的前缀bi,就成了通称的bilinear、bicubic。</P>
<P>线性插值公式比较简单,因此大家用的都差不多,基本算法的源码见<A
href="http://www.codeguru.com/bitmap/2_pass_scale.shtml">这里</A>,速度优化的代码见<A
href="http://www.codeguru.com/bitmap/SmoothBitmapResizing.html">这里</A>。但是线性插值算法只根据原图像上相邻的两个点来计算新图像上的点,插值误差随步长的增加而很快增加,因此一般认为不宜用于二倍以上的放大。在CEP和CV中,在线性插值放大后,还加了一道低通滤波处理,以减少锯齿。</P>
<P>三次插值根据原图像上相邻的四个点来计算新图像上的点,因此可以从更大范围内保证放大图像的平滑性,一般认为可以用于2倍以上的放大。很多商业图像编辑、浏览软件都采用了三次插值,包括Photoshop、ACDSEE
5.0等,mpeg4制作软件VirtualDub用的也是三次插值。</P>
<P>三次插值有两个特点:1、计算公式比较多,不同的样条基、不同的边界条件就可以产生不同的公式。2、属区域运算,运算量比较大,如果不考虑加速算法,大概不具有实用价值。</P>
<P>我最早得到的支持三次插值的图像处理库是Intel的Intel Image Process
Library(IPL)。这个库利用MMX指令集中的“单指令,多操作”来加速插值运算。我试用的结果,感觉对彩色图像效果不错,但是对黑白图像还是会有明显的锯齿,因此在“动画截图工具”系列中用这个库完成放大功能,但是在CEP和CV中没有采用。</P>
<P>后来到手了VirtualDub的源代码,但是被其中的大堆ASM吓到了,因此一直没有去研究。最近得到了最新版的<A
href="http://www.aoi.it/midcximage.html">CxImage</A>源代码,看到其中用C++写的三次插值放大,不由精神一振,可惜对它的速度和效果甚感失望,因此瞪着眼睛看了一下午,进行了两点改进:<BR>1、插值内核换成了标准Mitchell-Netravali双参数公式。CxImage原来用的公式似乎是Mitchell-Netravali双参数公式的某个特例,但是放大后的图像太模糊了,看得我好费劲,所以改成了最基本的Mitchell-Netravali双参数公式,参数取Mitchell和Netravali在他们的论文中推荐的(1/3,1/3)。<BR>2、对代码进行了彻底的C语言级优化,使速度达到可以接受的地步。但是因为没有进行ASM级优化,因此速度比其它软件可能差点,需要在高档一点的机器(近1G的CPU应该够了,我的是1G赛羊)上运行。优化完成后我再回过头来阅读VirtualDub的非MMX部分,才发现原来大家的优化思路完全一致,苦笑……</P>
<P>从VirtualDub的源代码看,它使用的也是Mitchell-Netravali双参数公式,但是非常奇怪,使用的参数对不是公认最好的(1/3,1/3),而是(0,-1)、(0,-0.75)、(0,-0.6),而且在源代码的注释中说明(0,-0.75)的效果与Photoshop相当,但是(0,-0.6)的效果会更好。从我使用的情况来看,这几组参数在放大后都会造成锐化效果,出现锯齿和颗粒,只不过(0,-0.6)的颗粒最小。后来又看了mpeg4播放插件bicubic_directshow_v1_3b_source,它用的是简化Mitchell-Netravali双参数公式,但是缺省参数对也是(1/3,1/3)!仔细想想,可能是因为压mpeg4的时候,画面缩小的概率比放大的概率大的原因吧?maybe……</P>
<P>CEP的放大算法除了bilinear、bicubic外,还有nearest(最近点)算法。这种算法的思想是这样的:遍历新图像的每一个点,把这个点的坐标按缩放比例反向折算成原图像的坐标,当然折算后的坐标值可能是个浮点数,比如说(1.2,2.3),原图像上离这个点“最近”的点是(1,2),则将(1,2)点的颜色值作为新图像上点的值,这就是算法名称nearest的来历。</P>
<P>nearest算法相当于查表运算,没有任何区域运算,因此速度飞快,但是质量实在是不怎么样,我个人认为不宜用于1.5倍以上的放大。ACDSEE
5.0以前的版本用的就是这种放大算法。</P>
<H2><A name=鸣谢><FONT color=#ff0000>鸣谢</FONT></A></H2>
<P>本程序的JPEG解码/编码采用了<A href="http://www.ijg.org/">Independent JPEG
Group</A>(独立JPEG小组)发布的<A
href="ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/">JPEG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -