RGB24转为灰度图本身并不难。基本方法就是计算象素的R、G、B分量的平均值(加起来除以3)。但是我想知道MMX指令能否帮助优化?初看完MMX指令的解释,觉得根本没法用在这个程序中。RGB24内存区是这样分布的:R1 G1 B1 R2 G2 B2 R3 G3 B3 ……。
现在要把它变成:(R1+G1+B1)/3 (R2+G2+B2)/3 (R3+G3+B3)/3 ……。这三个三个的,也没法用顺序分组,也没法用交错分组,也就更提不上一条加法指令计算多个象素了。何况还要除以3……。有没有高手能给我点提示或思路?谢谢!
现在要把它变成:(R1+G1+B1)/3 (R2+G2+B2)/3 (R3+G3+B3)/3 ……。这三个三个的,也没法用顺序分组,也没法用交错分组,也就更提不上一条加法指令计算多个象素了。何况还要除以3……。有没有高手能给我点提示或思路?谢谢!
解决方案 »
- truecrypt对U盘加密后, 如何防止该U盘被格式化?
- VC使用OLE自行化操作Excel的过程中,如果手工打开Excel文件然后关闭,VC程序出错.这个问题怎么解决?
- 关于系统托盘
- 求助:做过串口的各位大哥,PC 机是怎么收发上数据的?小弟急救!
- 怎么写接收信息的dll?
- sizeof(WSAPROTOCOL_INFO)这样写为什么出错?'WSAPROTOCOL_INFO' : undeclared identifier
- DCOM中接口函数的参数是否可以传递函数呢(高手救命呀!!!!!)
- 简单的程序分析,送分,5天后结帐
- 使用CString怎样把被分为两个字节的汉字还原为原来的一汉字?
- 拨号上网的提示窗口怎么做
- 悠视互动科技这个公司怎么样?
- vs2008开发activex的问题
char table[256*3];
int i;
for (i = 0; i < sizeof(table); i++) {
table[i] = i/3;
}
...
for (i = 0; i < picture_pixels; i+= 2) {
table(R[i]+G[i]+B[i]);
table(R[i+1]+G[i+1]+B[i+1]);
}
1) 无须除法
2) for里面2为单位处理,可以优化指令流水
1. 每次从源内存,假设在 edi 读3个64位的数,放在mm1, mm2, mm3
movq mm1, byte ptr [edi]
movq mm2, byte ptr [edi+8]
movq mm3, byte ptr [edi+16]
那么mm1, mm2, mm3里存放的数据是:
mm1: R1 G1 B1 R2 G2 B2 R3 G3
mm2: B3 R4 G4 B4 R5 G5 B5 R6
mm3: G6 B6 R7 G7 B7 R8 G8 B8
取三个常量作为R的掩码:R_Mask1 = 0xFF0000FF0000FF00
R_Mask2 = 0x00FF0000FF0000FF
R_Mask3 = 0x0000FF0000FF0000
有没有注意到三个掩码正好交错,取 mm4 = (mm1 & R_Mask1) | (mm2 & R_Mask2) | (mm3 & R_Mask3)
这时候 mm4 = R1 R4 R7 R2 R5 R8 R3 R6
正好是8个像素的R值,同样可以得到
mm5 = G6 G1 G4 G7 G2 G5 G8 G3
mm6 = B3 B6 B1 B4 B7 B2 B5 B8
关系就是依次左移8位
2. 把 mm4 unpack到两个64位寄存器中,对mm5, mm6作同样操作,然后对齐数据(懒了,不写了,基本就是用psllq之类的移位操作)
假设mm4 mm5 mm6都对齐了数据,比如
mm4: R1 0 R4 0 R7 0 R2 0
mm5: G1 0 G4 0 G7 0 G2 0
mm6: B1 0 B4 0 B7 0 B2 03. 最后是加起来除3的操作,这里建议看一下这篇文章 http://blog.csdn.net/zyl910/archive/2006/05/22/749752.aspx
把除法转换为加法和移位操作
0.299 R +0.587 G+0.114B=graylevel
这个是国际标准!
MMX指令问题就算了吧。
在发了这个帖子,又一时等不到回复时,一着急自己写想出你说的方法。所以看到你出的主意感到蛮亲切的呵呵~而且我觉得这个看似儿科的方法,其实在很多地方能够发挥意想不到的良好性能。攒一个!DRACULAX05:
没想到这么蹩脚的错位计算,还能用这种单指令多数据的方式处理啊,你头脑真够灵活的。不过我还一时看不懂,复制下来慢慢研究!感觉MMX的指令的思路很另类啊。rover:
你说的是求亮度的公式。当需要从图像中提取亮度时(比如RGB转YUV时),确实需要如你所说的运算,简单的除以3是不行的(否则转换后很多颜色无法区分了,比如纯红和纯蓝)。我最后的解决办法:我向公司算法部门的同事请教,一时没能拿到MMX版的程序,只是找到了一个能求亮度的,全整数运算的公式:
CLIP255((( 77*R + 150*G + 29*B + 128) >>8)); // 其中“CLIP255”自己顾名思义吧我没有仔细对比,但是心想大概应该是对求Y公式中的小数因数通分之后,再把分母尽量做成“除以256”,然后获得的计算式。估计我猜得应该差不多呵呵。