使用SSE4指令集优化双线性插值图像缩放

来源:互联网 发布:金钥匙软件下载 编辑:程序博客网 时间:2024/06/05 16:09

原理:

p = p(0) *(1-t) + p(1) * t = p(0) + (p(1) - p(0)) * t

水平方向和垂直方向均进行线性插值,缩放系数分别计算,由于水平和垂直成正交关系,因而与计算的先后次序无关。

 

缩放比例系数:

double scale_x = (des_width - 1)/(src_width - 1);

double scale_y = (des_height - 1)/(src_height - 1);

 

由于对图像进行采样时,索引从0开始,因而在计算缩放系数时应将宽高分别减1,以保证源和目的的最后一个采样点对齐。

 

计算权重和索引:

unsinged short* power;

unsinged short* map;

 

计算索引时,将浮点数进行截断取整,并保存为短整型。

计算权重时,将小数部分乘以16384并取整,即放大14位,这里采用整数计算而不是浮点计算。

 

缩放:

这里假设操作4通道32位颜色,如RGBA,其它颜色类似

以下代码为水平和垂直两个方向均进行缩放

void bl_hor_ver_out(int* des,int* src,int src_pitch,unsigned short* power_x,unsigned short* map_x, unsigned short power_y, int width){__asm{movedi, des;movesi, src;movedx, width;moveax, power_x;movebx, map_x;movzxecx, power_y;movdxmm7, ecx;pshuflwxmm7, xmm7, 0;shufpdxmm7, xmm7, 0;testedx, edx;jzloop_end;loop_1:movzxecx, word ptr [ebx];// 取出索引pmovzxbwxmm0, [ecx * 4 + esi];// 取出第一行两个像素addesi, src_pitch;pmovzxbwxmm1, [ecx * 4 + esi];// 取出第二行两个像素subesi, src_pitch;movzxecx, word ptr [eax];// 取出水平方向权重psubwxmm1, xmm0;// p(1) - p(0)movdxmm2, ecx;psllwxmm1, 2;// 放大2位pshuflwxmm2, xmm2, 0;pmulhwxmm1, xmm7;        // (p(1) - p(0)) * ty,取高16位,得出未放大的结果paddwxmm0, xmm1;// p(0) + ((p(1) - p(0)) * typshufdxmm1, xmm0, 0x0e;psubwxmm1, xmm0;psllwxmm1, 2;pmulhwxmm1, xmm2;// ((p(1) - p(0)) * txpaddwxmm1, xmm0;// p(0) + ((p(1) - p(0)) * txpackuswbxmm1, xmm1;movd[edi], xmm1;addedi, 4;addeax, 2;addebx, 2;decedx;jnzloop_1;loop_end:}}



 

 

扩展:

(1)还可对上述代码进行优化,可采取一次计算两个像素,这样水平方向两个像素采用一个乘法指令(pmulhw);

(2)当只有水平方向或只有垂直方向进行缩放时,应该独立实现缩放函数,以提高效率,如函数名可为bl_hor_out, bl_ver_out;

(3)如果需要高精度,需要进行浮点计算,同时考虑补偿防止截断

 

英文链接:http://en.wikipedia.org/wiki/Bilinear_interpolation

原创粉丝点击