/* 转载请注明出处:http://www.cnblogs.com/Martinium/articles/a_bit_of_fun.html */

OK, 先上一张很有喜感的图片~~

Morphing 关于图像的渐变的原理很简单。找准对应的锚点,即从源图中的点对应目标图中的点(比如眼睛、鼻子、嘴巴、脸的轮廓等那些高频分量地方),高频区域取锚点稠密点、低频区域取锚点稀疏些,这样使得撒的锚点少并且得到的效果好。然后根据公式

out = t*dst + (1-t)*src,(0 <= t <= 1)

参数 t 取值从 0 变化到 1的时候,得到的图像就是从 src 渐变到 dst,取一些关于 t 的值生成的中间图像,调用 giflib 的 API 写入 GIF 格式图像中。关于 t=f(x), (0 <= x <= 1) 的取值,你也可以作点文章。线性函数 f(x)=x,可以得到均匀变化的效果;二次函数 f(x)=x2,可以得到渐快的效果;三次函数 f(x)=4*(x-0.5)3+0.5,你可以得到类似子弹时间的效果,一种先变慢然后又加快的效果。

稍微讨论一下上面的公式,3D 图像的 Alpha Blending 以及一般的图像处理软件里面的图层叠加都有它的影子。

factor*dst + (1-factor)*src = src + factor*(dst-src)

这里稍微变形一下,省去了一个乘法。对一个像素来说简直微不足道,想想处理一个上百万像素的图片,这个省略还是可观的。毕竟乘法比加法“贵”多了。省去一个乘法能降低算法的复杂度。例如:Gauss 的复数乘法算法、大数乘法的分而治之把复杂度从O(n^2)降到O(n^log(3))、矩阵乘法的分而治之把复杂度从O(n^3)降到O(n^log(7)) 等。请参考文件 Divide-and-conquer algorithms。

现在切入主题。其实我要讲的是位操作——一个与上面的公式极类似的式子。 它用在 3D 图像的模板缓冲(stencil buffer)中,模板测试的通过或失败决定了像素的颜色值是否要被写入到渲染目标(render target)。

src&~mask | dst&mask = src^((src^dst)&mask)

鉴于 C 语言运算符优先级顺序从大到小依次为 ~ & ^ |,所以左边没有加括号。式子的意思是根据掩码 mask 合并 src 和 dst 的 bit 位。公式左边 4 个位操作运算,右边 3 个位操作运算,节约了一个。虽然实际用意不大,但是已经找到乐趣了。当然,如果 mask 是个常数的话,就没有优势了,编译器会直接计算出 ~mask,从而左边也是3个位操作符。

src^((src^dst)&mask)
=src&~((src^dst)&mask) | ~src&((src^dst)&mask)               a^b = a&~b | ~a&b
=src&(~(src^dst)|~mask) | ~src&((src^dst)&mask)              ~(a&b) = ~a|~b
=src&(~(src^dst)|~mask) | (~src&(src^dst))&mask              a&(b&c) = (a&b)&c
=src&~(src^dst) | src&~mask | (~src&(src^dst))&mask        a&(b|c) = (a&b)|(a&c)
=src&~(src^dst) | src&~mask | ~src&dst&mask                   a&(b^c) = (a&b)^(a&c)
=src&dst | src&~mask | ~src&dst&mask
=src&~mask | (dst&src | dst&(~src&mask))
=src&~mask | dst&(src|(~src&mask))
=src&~mask | dst&(src|mask)
=src&~mask | dst&mask | src&dst
=src&~mask | dst&mask

稍微证明了下倒数第二步多出的项 src&dst 有一部分在 src&~mask,另一部分在 dst&mask,可以添上或抹掉。
证明可真繁琐,还是上文氏图吧。图中斜线部分表示的就是等式的值。

意犹未尽,再补充一下 xor。

1. 字符串的大小写转换 toupper/tolower 存在于 ctype.h 头文件。

#define _tolower(_Char) ( (_Char)-'A'+'a' )
#define _toupper(_Char) ( (_Char)-'a'+'A' )

有了异或操作,你可以这么写:
小写变大写    ch &= ~(‘a’^'A');  
大写变小写    ch  |= ‘a’^'A'; 
大小写切换    ch ^= ‘a’^'A';

2. 交换两个整形。

void swap1(int &a, int &b)
{int tmp = a;a = b;b = tmp;
}void swap2(int &a, int &b)
{a += b;b = a - b;a -= b;
}void swap3(int &a, int &b)
{a ^= b ^= a ^= b;
}

swap1 占用一个临时空间来交换。swap2 和 swap3 没有使用临时空间。
swap2 用自己当临时空间,似乎有整形溢出的危险,但是不影响结果的正确性。(如果溢出,第一步的溢出会在第二步拾回来。)
swap3 使用 ^= 操作符一气呵成,从右向左计算,与 swap2 思想相同,但不会让你有种溢出的感觉:-)

在 OpenGL 中,可以利用 glCopyPixels() 函数(使用XOR操作)交换相同大小的图像。因为 glCopyPixels() 函数不需要 format 或 data 参数,所以数据不会复制到内存中。通过这种方法,可以避免把图像读回到处理器内存的开销。如果 A 和 B 表示两幅图像,图像交换操作可以写成 A=A XOR B, B=A XOR B, A=A XOR B; 也就是上面的 swap3。

转载于:https://www.cnblogs.com/Martinium/archive/2013/06/15/a_bit_of_fun.html

最新文章

  1. 如何使用github托管项目---快速入门(菜鸟教程)
  2. shell脚本的规范
  3. 问题集锦(30-35)
  4. [YTU]_2441( C++习题 复数类--重载运算符2+)
  5. C语言 | 6种常用的转换工具函数盘点
  6. sam格式的结构和意义_各种格式的练字本,对写字真有帮助吗
  7. vue3 @/cli脚手架搭建项目
  8. php文档头,头部文档(header.php)
  9. VNC 远程重装 Linux
  10. CSDN怎么获取下载积分
  11. 【转载】读透《哥德尔、艾舍尔、巴赫:集异璧之大成》
  12. 基于WIKI中文语料·Word2Vec模型训练·Python
  13. xfce实现桌面图标透明
  14. 微信群超好用的红包抽奖小程序
  15. 啥? 代码可以改变世界? 道翰天琼认知智能API接口平台为您揭秘。
  16. 集群运维:All datanodes DatanodeInfoWithStorage[10.21.131.179:50010,DS-6fca3fba-7b13-4855-b483-342df8432e
  17. Fiddler使用介绍
  18. import导包方法和路径问题和init方法调用流程
  19. Java二叉树后序遍历:递归与迭代
  20. 翁恺《C语言程序设计》(第四版)何钦铭 例题+练习题代码 第八章-指针

热门文章

  1. DataGridView多线程更新数据的问题的解决办法
  2. 用Python编写干净 可测试 高质量的代码
  3. 蓝桥杯 ALGO-80 算法训练 整数平均值
  4. 【软件测试】α测试和β测试的区别
  5. 1121. Damn Single (25)-PAT甲级真题
  6. 用计算机制作模拟,计算机模拟设计,computer simulation design,音标,读音,翻译,英文例句,英语词典...
  7. 云服务器在哪里创建网站目录,如何在云服务器创建根目录
  8. 计算机文化理论基础考试单机版,计算机文化基础授课计划表
  9. python的浮点数_python – range()用于浮点数
  10. DNS解释问题:java.net.UnknownHostException