在我的程序中图像处理函数是作为 DirectShow 封装类一部分的,我认为这样便于移动和使用.
图像处理
在我的程序中图像处理函数是作为 DirectShow 封装类一部分的,我认为这样便于移动和使用。没有连着上面的 DirectShow 类而另外写标题是因为我觉得有必要把它提到重要位置。在程序完善阶段您的工作基本就在这里了,除了花心思构造D3D环境外几乎所有效果都要在这里实现,水平高下也体现于此。
在网上可以找到很多图像特效的代码和解说,我结合编程过程再说说。
1. 访问缓冲区的麻烦。
这是最麻烦的,二维图像在这里以一个连续的一维缓冲区呈现,您要靠一个指针去访问它,怎么办呢?先弄懂 Pitch,例如 32bit ARGB 图像,每个象素就占用 4 Byte 内存空间(1 Byte = 8 bit),对于宽度为 20 像素的图像,它的 Pitch 就是 80 Byte,即每一行占用的内存。按 x 、y 坐标就有如下公式(按 Byte 计算):
B:y * Pitch + x * 4 G:y * Pitch + x * 4 + 1 R:y * Pitch + x * 4 + 2 A:y * Pitch + x * 4 + 3 |
可以看出在内存中是按 BGRA 存储的,我不明白为什么这样,可能可以从计算机的内存存储方式找到答案。上述公式计算多,效率较低,在实际使用中应适时作有益的改变。
2. 浮雕。
到目前为止我在网上找到的几篇文章都说把一点的值减去其右下角点的值再加上128就行了。为什么要减去右下角的点呢?为什么要加上128呢?原来浮雕是要把图像的变化部分突出显示出来,而把相同部分淡化,所以用一点减去其邻域任意点都可以达到这个目的,倒也不一定是右下角的点,包围着它的八个点都可以,甚至可以选择减去更远的点,只要规则明确、效果好就行。在相减后点的 RGB 值都减小了,大多接近黑色,黑乎乎一片的看不出什么来,一点也不像浮雕,所以要给它们都增加一个相同的亮度,通常加上128,其它的值,例如64、100,当然也行,一切都以实际效果为准。说到效果,上面所说的RGB相减会造成浮雕有一些色点,解决方法是计算两点的亮度之差,RGB都赋值为亮度差,画面就没色点了,因为已经变成灰度图了。亮度公式是 Brightness = 0.3 * R + 0.6 * G + 0.1 * B,其中G 的比重最大,可以近似的用 G 作为亮度,在RGB各自的分量图中也可以明显看出 G 分量的图最亮,简单的把 G 的值赋给 R 和 B 就得到灰度图了,这可以减少计算,提高速度。后来我还看到这样的话句,"用3 * 3 的小块做的浮雕效果更好",不过我不知道怎么用,可能这样就可以实现 PhotoShop 那样更好的浮雕效果。
原理是这样了,到了编程却是另外一回事:能够把规则、数学公式转换为程序也是能力的一种体现。如果要减去右下角的点,那么最右一列和最后一行是要特殊处理的,否则肯定会发生内存访问错误,想一想就知道为什么;如果要减去左边的点,第一列也要特殊处理,请问第一列的点到哪里找它左边的点呢?不要小视此问题,它会令你访问内存时遇到一些问题。
3. 铅笔画
铅笔画原理和浮雕差不多,也是亮度相减,认为变化大的是边缘,然后设置一个阀值,例如差值大于8,则把该点设为黑色(0,0,0),要不设为白色(255,255,255)。阀值、色彩都可任意设置,没人要您拘束就不要忸忸怩怩的不敢改动。
按照此方法得到的效果实在不怎么样,可惜我不是研究图像的料,对数据的处理能力很差,同样一幅在专家手中可以玩出很多花样的图片,沦落到我手上也只能饮恨屈膝投降无奈了。这是我看了一些图像处理方面资料和书籍所发的呆叹,图像处理实在太精深了,既要数学、物理知识雄厚,又要脑子灵活能东移西就把各种知识综合运用,不然就只好望洋兴叹。
4. 加亮、对比度等
首先悲痛的说明,我曾努力的要实现色度、饱和度的调整,知道是要把 RGB 转换成 HLS 之类的颜色空间才能实现,也找到了一些它们之间转换的说明和转换函数,可惜看不明白,或者说那些材料根本不打算让我明白!这不单是气话,而且事实,我真的十分气愤:怎么能够在前面铺了一大堆"效果图"说了一大堆废话然后给个只有几行无大用的注释的代码就可以呢?!尽管如此愤概,我还是乖乖的抄了程序,希冀能发挥作用,结果却是失望:不仅效率低下,而且在调整了饱和度的同时使图像出现不协调的彩色方块。由于不知道原理,无法改动,于是我放弃了它。
调整亮度很简单,例如要加亮 10,把 RGB 都加上 10 就可以了,减亮就减10。
对比度调整也不难,书上说是要令亮点更亮、暗点更暗,好像是要找出亮点来增亮、找出暗点加暗,其实不然,把所有点都乘以一个数,把亮暗点的差距拉大或减小就能调整对比度了。把图像原来的对比度定为 1,要增大对比度就调整为 1.3 、2 等大于1 的数,把每个点的 RGB 都乘以它,就行了,要降低就把数值设为 0 至 1 的数。只要注意保持 RGB 的值在 0 ~ 255 中即可。