权当练手了,效果不好,cpu没有提供pmulluw这样一个无符号字相乘指令。
处理的效果和matlab明显不同,尤其是背景,我实在找不出问题在哪里,最可能就在寄存器符号上。
灰度公式是:Gray = (R*76 + G*150 + B*30) >> 8
有符号范围是[-32768-32767],无符号范围是[0-65536],前者显然不够存放255*150=38250的,所以就溢出了。
提高了位宽模拟无符号相乘不行,减小运算精度也不行,开源节流都不行,让人很纠结。
反正是初学,这指令还要多练才行。
VOID asmARGB2Gray(BitmapData *data) { UINT Height=data->Height; UINT Width=data->Width; Pix* p=(Pix*)data->Scan0; UINT n=Height*Width; Pix cp[]={0x014c961e}; __asm { push esi; mov ecx,n; pxor mm7,mm7; mov esi,[p]; movd mm2,[cp]; lp: movq mm1,mm2; movd mm0,[esi]; //mm0:00 00 00 00 Alpha R G B mov al,[esi+3]; //al:Alpha punpcklbw mm0,mm7; //mm0:00 Alpha 00 R 00 G 00 B punpcklbw mm1,mm7; //mm1:00 01 00 4c 00 96 00 1e movq mm3,mm0; movq mm5,mm1; //模拟 pmulluw movq mm4, mm5 pmullw mm5, mm3 /* a * b lo 16×16 unsigned */ pmulhuw mm4, mm3 /* a * b hi 16×16 unsigned */ movq mm6, mm5 punpcklwd mm5, mm4 punpckhwd mm6, mm4 movq mm0,mm5; movq mm1,mm6; psrlw mm0,8; psrlw mm1,8; packssdw mm0,mm0; packssdw mm1,mm1; movd edx,mm0; movd ebx,mm1; shr edx,16; add dl,bl; shr ebx,16; add dl,bl; mov [esi], dl; mov [esi+1],dl; mov [esi+2],dl; mov [esi+3],al; add esi,4; dec ecx; jnz lp; pop esi; emms; } }
效果:
和matlab处理的明显不一样嘛