processingMMX.inl
上传用户:fengshi120
上传日期:2014-07-17
资源大小:6155k
文件大小:54k
源码类别:

3D图形编程

开发平台:

C/C++

  1. /*************************************************************************** 
  2. *
  3. * Copyright 2000 by David Demirdjian.   All rights reserved. 
  4. *  
  5. * Developed  by David Demirdjian
  6. *  
  7. * Permission to use, copy, or modify this software and  its documentation 
  8. * for  educational  and  research purposes only and without fee  is hereby 
  9. * granted, provided  that this copyright notice and the original authors's 
  10. * names appear  on all copies and supporting documentation.  If individual 
  11. * files are  separated from  this  distribution directory  structure, this 
  12. * copyright notice must be included.  For any other uses of this software, 
  13. * in original or  modified form, including but not limited to distribution 
  14. * in whole or in  part, specific  prior permission  must be  obtained from 
  15. * MIT.  These programs shall not  be  used, rewritten, or  adapted as  the 
  16. * basis  of  a  commercial  software  or  hardware product  without  first 
  17. * obtaining appropriate  licenses from David Demirdjian.  The author makes 
  18. * no representations about the suitability of this software for any purpose.  
  19. * It is provided "as is" without express or implied warranty. 
  20. *  
  21. **************************************************************************/
  22. #include "stereoMatching.h"
  23. #include "processingMMX.h"
  24. // ************************************************************
  25. // ************************************************************
  26. // *** List of functions (MMX) for image processing
  27. // ************************************************************
  28. // ************************************************************
  29. // shrink images by a factor 'fact'. eg if fact = 2, out will be twice as small as src
  30. inline void shrinkImages(uchar* dst, const uchar* src, int width, int height, int fact)
  31. {
  32. int width_f = width/fact;
  33. int siz = width*height/(fact*fact);
  34. if (fact>0) {
  35. for (int i=0,j=0; i<siz; ++i,++j,++dst,src+=fact) {
  36. *dst = *src;
  37. if (j==width_f-1) {
  38. src+=((fact-1)*width);
  39. j=0;
  40. }
  41. }
  42. }
  43. }
  44. // translate image of 'tx' pixels to the right
  45. // (or left if tx<0)
  46. void translateImage(int tx, uchar* data, int siz)
  47. {
  48. if (tx==0) return; 
  49. if (tx>0) {
  50. // dest. must be after src... to avoid overwriting data
  51. data += (siz-tx);
  52. uchar* dataDst = data+tx;
  53. for (int i=0; i<siz-tx; ++i,--dataDst,--data) {
  54. *dataDst = *data;
  55. }
  56. } else { // tx<0
  57. data -= tx;
  58. uchar* dataDst = data+tx;
  59. for (int i=0; i<siz-tx; ++i,++dataDst,++data) {
  60. *dataDst = *data;
  61. }
  62. }
  63. }
  64. void normalizeImages(uchar* data1, uchar* data2, uchar* data3, int siz)
  65. {
  66. float a1 = pixelMean(data1,siz);
  67. float a2 = pixelMean(data2,siz);
  68. float a3 = pixelMean(data3,siz);
  69. float minI = __min(a1, __min(a2,a3));
  70. if (a2==minI) {
  71. multiply(data1, a2/a1, siz);
  72. multiply(data3, a2/a3, siz);
  73. } else if (a1==minI) {
  74. multiply(data2, a1/a2, siz);
  75. multiply(data3, a1/a3, siz);
  76. } else {
  77. multiply(data2, a3/a2, siz);
  78. multiply(data1, a3/a1, siz);
  79. }
  80. }
  81. void normalizeImages(const uchar* data1, const uchar* data2, const uchar* data3, 
  82.  uchar* out1, uchar* out2, uchar* out3, int siz)
  83. {
  84. float a1 = pixelMean(data1,siz);
  85. float a2 = pixelMean(data2,siz);
  86. float a3 = pixelMean(data3,siz);
  87. float minI = __min(a1, __min(a2,a3));
  88. if (a2==minI) {
  89. multiply(data1, out1, a2/a1, siz);
  90. multiply(data3, out3, a2/a3, siz);
  91. copyMMX(out2, data2, siz);
  92. } else if (a1==minI) {
  93. multiply(data2, out2, a1/a2, siz);
  94. multiply(data3, out3, a1/a3, siz);
  95. copyMMX(out1, data1, siz);
  96. } else {
  97. multiply(data2, out2, a3/a2, siz);
  98. multiply(data1, out1, a3/a1, siz);
  99. copyMMX(out3, data3, siz);
  100. }
  101. }
  102. void normalizeImages(uchar* data1, uchar* data2, int siz)
  103. {
  104. float a1 = pixelMean(data1,siz);
  105. float a2 = pixelMean(data2,siz);
  106. // normalize the image which average intensity is the highest
  107. if (a1>a2) 
  108. multiply(data1, a2/a1, siz);
  109. else 
  110. multiply(data2, a1/a2, siz);
  111. }
  112. void normalizeImages(const uchar* data1, const uchar* data2, 
  113.  uchar* out1, uchar* out2, int siz)
  114. {
  115. float a1 = pixelMean(data1,siz);
  116. float a2 = pixelMean(data2,siz);
  117. // normalize the image which average intensity is the highest
  118. if (a1>a2) {
  119. multiply(data1, out1, a2/a1, siz);
  120. copyMMX(out2, data2, siz);
  121. } else {
  122. multiply(data2, out2, a1/a2, siz);
  123. copyMMX(out1, data1, siz);
  124. }
  125. }
  126. //  ImgSub2: D = saturation0(|S1 - S2| + |S1 - S3|)
  127. // TODO? divide the result by 2 (shift)
  128. inline int ImgSubandAdd(const unsigned char *Src1, const unsigned char *Src2, 
  129.  const unsigned char *Src3, unsigned char *Dest, int l)
  130. {
  131. if (l < 8) return 0;              // image size must be at least 8 bytes 
  132.   __asm 
  133.   {
  134.         mov eax, Src1     
  135.         mov ebx, Src2
  136. mov edx, Src3
  137.         mov edi, Dest    
  138.         mov ecx, l   
  139.         shr ecx, 3
  140. align 16
  141. inner_loop:
  142. movq mm1,[eax] // mm1=src1
  143. movq mm2,[ebx] // mm2=src2
  144. movq mm4,mm1 // mm4=mm1
  145. psubusb mm4,mm2 // mm4 = src1 - src2
  146. movq mm3,[edx] // mm3=src3
  147. psubusb mm2,mm1 // mm2 = src2 - src1
  148.         
  149. movq mm5,mm1 // mm5=src1
  150. por mm2,mm4 // mm2=|src1-src2|
  151.         psubusb mm5,mm3 // mm4=src1-src3
  152.         psubusb mm3,mm1   // mm3=src3-src1
  153. por mm3,mm5 // mm3=|src1-src3|
  154. paddusb mm2,mm3 // mm2 = |src1-src2|+|src1-src3|
  155.         movq    [edi], mm2  
  156.         add eax,8         
  157.         add ebx,8     
  158.         add edx,8     
  159.         add edi,8
  160.         dec ecx      
  161.         jnz inner_loop    
  162.         emms   
  163.   }
  164.   return 1;
  165. }
  166. //  ImgSub2: D = saturation0(|S1 - S2|)
  167. // TODO? divide the result by 2 (shift)
  168. inline int ImgSubandAdd(const unsigned char *Src1, const unsigned char *Src2, 
  169.  const unsigned char *Dest, int l)
  170. {
  171. if (l < 8) return 0;              // image size must be at least 8 bytes 
  172.   __asm 
  173.   {
  174.         mov eax, Src1     
  175.         mov ebx, Src2
  176.         mov edi, Dest    
  177.         mov ecx, l   
  178.         shr ecx, 3
  179. align 16
  180. inner_loop:
  181. movq mm1,[eax] // mm1=src1
  182. movq mm2,[ebx] // mm2=src2
  183. movq mm4,mm1 // mm4=mm1
  184. psubusb mm4,mm2 // mm4 = src1 - src2
  185. psubusb mm2,mm1 // mm2 = src2 - src1  
  186. por mm2,mm4 // mm2=|src1-src2|
  187.         movq    [edi], mm2  
  188.         add eax,8         
  189.         add ebx,8     
  190.         add edi,8
  191.         dec ecx      
  192.         jnz inner_loop    
  193.         emms   
  194.   }
  195.   return 1;
  196. }
  197. #define _ABS_DIFF_TRI(Z) __asm 
  198. __asm movq mm4,mm1 /* mm4=mm1 */ 
  199. __asm add ebx, width  
  200. __asm add edi, imageSize 
  201. __asm por mm3,mm7 /* here mm2=new src2 mm3=new src3 */ 
  202. __asm movq mm7, mm0 
  203. __asm psubusb mm4,mm2 /* mm4 = src1 - src2 */ 
  204. __asm psubusb mm2,mm1 /* mm2 = src2 - src1 */ 
  205. __asm psllq mm7,Z
  206. __asm movq mm5,mm1 /* mm5=src1 */ 
  207. __asm por mm4,mm2 /* mm2=|src1-src2| */ 
  208. __asm movq mm2,[ebx] /* mm2= src2 + 'width' = new src2*/ 
  209. __asm psubusb mm5,mm3 /* mm5=src1-src3*/ 
  210. __asm movq mm6,mm3 /* mm6=src3*/ 
  211.     __asm   psubusb mm6,mm1   /* mm3=src3-src1*/ 
  212. __asm por mm6,mm5 /* mm6=|src1-src3|*/ 
  213. __asm paddusb mm4,mm6 /* mm4 = |src1-src2|+|src1-src3|*/ 
  214. __asm movq    [edi], mm4  /* here mm1=src1*/  
  215. __asm psrlq mm3, 8 /* mm3 = src3 + '1' ... with [x00000000] at the end*/
  216. }
  217. #define _ABS_DIFF_TRI_prefetch(Z, X) __asm 
  218. __asm movq mm4,mm1 /* mm4=mm1 */ 
  219. __asm add ebx, width  
  220. __asm add edi, imageSize 
  221. __asm por mm3,mm7 /* here mm2=new src2 mm3=new src3 */ 
  222. __asm movq mm7, mm0 
  223. __asm psubusb mm4,mm2 /* mm4 = src1 - src2 */ 
  224. __asm psubusb mm2,mm1 /* mm2 = src2 - src1 */ 
  225. __asm   prefetcht0 [ebx + X] 
  226. __asm psllq mm7,Z
  227. __asm movq mm5,mm1 /* mm5=src1 */ 
  228. __asm por mm4,mm2 /* mm2=|src1-src2| */ 
  229. __asm movq mm2,[ebx] /* mm2= src2 + 'width' = new src2*/ 
  230. __asm psubusb mm5,mm3 /* mm5=src1-src3*/ 
  231. __asm movq mm6,mm3 /* mm6=src3*/ 
  232.     __asm   psubusb mm6,mm1   /* mm3=src3-src1*/ 
  233. __asm por mm6,mm5 /* mm6=|src1-src3|*/ 
  234. __asm paddusb mm4,mm6 /* mm4 = |src1-src2|+|src1-src3|*/ 
  235. __asm movq    [edi], mm4  /* here mm1=src1*/  
  236. __asm psrlq mm3, 8 /* mm3 = src3 + '1' ... with [x00000000] at the end*/
  237. }
  238. //  ImgSubandAdd2: D = saturation0(|S1 - S2| + |S1 - S3|)
  239. // process 8 disparities at a time
  240. //
  241. // Src1: right
  242. // Src2: top
  243. // Src3: left
  244. //
  245. // TODO? divide the result by 2 (shift)
  246. inline int ImgSubandAdd2(const unsigned char *Src1, const unsigned char *Src2, 
  247.  const unsigned char *Src3, 
  248.  unsigned char* Dest1, int l, int imageSize, int width)
  249. {
  250. if (l < 8) return 0;              // image size must be at least 8 bytes 
  251. const int back_step1 = 7*width;
  252. const int back_step2 = 7*imageSize;
  253.   __asm 
  254.   {
  255.         mov eax, Src1     
  256.         mov ebx, Src2
  257. mov edx, Src3
  258.         mov edi, Dest1   
  259.         mov ecx, l   
  260.         shr ecx, 3
  261. movq mm0,[edx] // mm0=src3
  262. movq mm0,[edx] // mm0=src3
  263. align 16
  264. inner_loop:
  265. movq mm1,[eax] // mm1=src1
  266. movq mm3,mm0 // mm3=src3
  267. movq mm2,[ebx] // mm2=src2
  268.         add eax,8         
  269.  
  270. // -- 1 --------- in : mm1,mm2,mm3     out: mm4=SAD  mm2=new mm2 --
  271. movq mm4,mm1 // mm4=mm1
  272. add ebx,width
  273. psubusb mm4,mm2 // mm4 = src1 - src2
  274. //prefetcht0 [ebx + 32 + 2*320]
  275. movq mm0,[edx+8]
  276. psubusb mm2,mm1 // mm2 = src2 - src1
  277.         
  278. movq mm5,mm1 // mm5=src1
  279. por mm4,mm2 // mm2=|src1-src2|
  280. movq mm2,[ebx] // mm2= src2 + 'width' = new src2
  281. psubusb mm5,mm3 // mm5=src1-src3
  282. movq mm6,mm3 // mm6=src3
  283.         psubusb mm6,mm1   // mm3=src3-src1
  284. movq mm7, mm0
  285. psrlq mm3, 8 // mm3 = src3 + '1' ... with [x00000000] at the end
  286. por mm6,mm5 // mm6=|src1-src3|
  287. paddusb mm4,mm6 // mm4 = |src1-src2|+|src1-src3|
  288.         movq    [edi], mm4  
  289. psllq mm7, 56 // here mm1=src1 mm2=NEW src2 mm3=begin of NEWsrc3    mm7=end of NEWsrc3
  290. // -------------------------------------------------------------
  291. // - 2 ----------------
  292. _ABS_DIFF_TRI(48)
  293.   // - 3 ----------------
  294. _ABS_DIFF_TRI(40)
  295.   // - 4 ----------------
  296. _ABS_DIFF_TRI(32)
  297. // _ABS_DIFF_TRI_prefetch(32,24 + 3*320)
  298. // - 5 ----------------
  299. _ABS_DIFF_TRI(24)
  300. // - 6 ----------------
  301. _ABS_DIFF_TRI(16)
  302. // - 7 ----------------
  303. _ABS_DIFF_TRI(8)
  304. // - 8 ----------------
  305. movq mm4,mm1 // mm4=mm1
  306. por mm3,mm7 // here mm2=new src2 mm3=new src3
  307. psubusb mm4,mm2 // mm4 = src1 - src2
  308. psubusb mm2,mm1 // mm2 = src2 - src1
  309.         
  310. movq mm5,mm1 // mm5=src1
  311. por mm4,mm2 // mm2=|src1-src2|
  312. psubusb mm5,mm3 // mm5=src1-src3
  313.         psubusb mm3,mm1   // mm3=src3-src1
  314. por mm3,mm5 // mm6=|src1-src3|
  315. paddusb mm4,mm3 // mm4 = |src1-src2|+|src1-src3|
  316. add edi, imageSize
  317.         movq    [edi], mm4  // here mm1=src1
  318. // -------------------------------------------------------------
  319.   // 
  320. sub ebx, back_step1
  321.         add ebx,8
  322.         add edx,8     
  323. sub edi, back_step2
  324.         add edi,8
  325.         dec ecx      
  326.         jnz inner_loop    
  327.         emms   
  328.   }
  329.   return 1;
  330. }
  331. // macro: in: mm1,mm2
  332. #define _ABS_DIFF_ __asm 
  333. __asm  movq mm4,mm1  /* mm4=mm1 */ 
  334. __asm  psubusb mm4,mm2  /* mm4 = src1 - src2 */ 
  335. __asm  psubusb mm2,mm1  /* mm2 = src2 - src1 */ 
  336. __asm  por  mm4,mm2  /* mm2=|src1-src2| */ 
  337. __asm  add ebx, width 
  338. __asm  add edi, imageSize 
  339.     __asm  movq mm2,[ebx] 
  340. __asm  movq [edi], mm4   /* here mm1=src1  */ 
  341. }
  342. //  ImgSubandAdd2: D = saturation0(|S1 - S2| + |S1 - S3|)
  343. // process 8 disparities at a time
  344. // Src1: right
  345. // Src2: top
  346. // TODO? divide the result by 2 (shift)
  347. inline int ImgSubandAdd2_Vert(const unsigned char *Src1, const unsigned char *Src2, 
  348. unsigned char* Dest1, int l, int imageSize, int width)
  349. {
  350. if (l < 8) return 0;              // image size must be at least 8 bytes 
  351. const int back_step1 = 7*width;
  352. const int back_step2 = 7*imageSize;
  353.   __asm 
  354.   {
  355.         mov eax, Src1     
  356.         mov ebx, Src2
  357.         mov edi, Dest1   
  358.         mov ecx, l   
  359.         shr ecx, 3
  360. align 16
  361. inner_loop:
  362. movq mm1,[eax] // mm1=src1
  363. movq mm2,[ebx] // mm2=src2
  364.         add eax,8         
  365.  
  366. // -- 1 --------- in : mm1,mm2,mm3     out: mm4=SAD  mm2=new mm2 --
  367. _ABS_DIFF_
  368. _ABS_DIFF_
  369. _ABS_DIFF_
  370. _ABS_DIFF_
  371. _ABS_DIFF_
  372. _ABS_DIFF_
  373. _ABS_DIFF_
  374. // - 8 ----------------
  375. movq mm4,mm1 // mm4=mm1
  376. psubusb mm4,mm2 // mm4 = src1 - src2
  377. psubusb mm2,mm1 // mm2 = src2 - src1
  378.         
  379. por mm4,mm2 // mm2=|src1-src2|
  380. add edi, imageSize
  381.         movq    [edi], mm4  // here mm1=src1
  382. // -------------------------------------------------------------
  383.   // 
  384. sub ebx, back_step1
  385.         add ebx,8
  386.   sub edi, back_step2
  387.         add edi,8
  388.         dec ecx      
  389.         jnz inner_loop    
  390.         emms   
  391.   }
  392.   return 1;
  393. }
  394. // macro: in: mm1,mm2
  395. #define _ABS_DIFF_HORIZ(Z) __asm 
  396. __asm  movq mm7, mm0 
  397. __asm  add edi, imageSize 
  398. __asm  movq mm5,mm1 /* mm5=src1 */ 
  399. __asm  psllq mm7, Z 
  400. __asm  psubusb mm5,mm3 /* mm5=src1-src3 */ 
  401. __asm  movq mm6,mm3 /* mm6=src3 */ 
  402.     __asm  psubusb mm6,mm1   /* mm3=src3-src1 */ 
  403. __asm  por mm6,mm5 /* mm6=|src1-src3| */ 
  404.     __asm  movq    [edi], mm6  /* here mm1=src1 */ 
  405. __asm  psrlq mm3, 8 /* mm3 = src3 + '1' ... with [x00000000] at the end */ 
  406. __asm  por mm3,mm7 /* here mm3=new src3 */ 
  407. }
  408. //  ImgSubandAdd2: D = saturation0(|S1 - S2| + |S1 - S3|)
  409. // process 8 disparities at a time
  410. //
  411. // Src1: right
  412. // Src2: top
  413. // Src3: left
  414. //
  415. // TODO? divide the result by 2 (shift)
  416. inline int ImgSubandAdd_Horiz(const unsigned char *rightIm, const unsigned char *leftIm, 
  417.  unsigned char* Dest, int l, int imageSize, int width)
  418. {
  419. if (l < 8) return 0;              // image size must be at least 8 bytes 
  420. const int back_step2 = 7*imageSize;
  421.   __asm 
  422.   {
  423.         mov eax, rightIm     
  424.   mov edx, leftIm
  425.         mov edi, Dest 
  426.         mov ecx, l   
  427.         shr ecx, 3
  428. movq mm0,[edx] // mm0=src3
  429. movq mm0,[edx] // mm0=src3
  430. align 16
  431. inner_loop:
  432. movq mm1,[eax] // mm1=src1
  433. movq mm3,mm0 // mm3=src3
  434. // -- 1 --------- in : mm1,mm2,mm3     out: mm4=SAD  mm2=new mm2 --
  435. movq mm0,[edx+8]
  436.         add eax,8         
  437.    
  438. movq mm5,mm1 // mm5=src1
  439. psubusb mm5,mm3 // mm5=src1-src3
  440. movq mm6,mm3 // mm6=src3
  441.         psubusb mm6,mm1   // mm3=src3-src1
  442. movq mm7, mm0
  443. psrlq mm3, 8 // mm3 = src3 + '1' ... with [x00000000] at the end
  444. por mm6,mm5 // mm6=|src1-src3|
  445.         movq    [edi], mm6  
  446. psllq mm7, 56 // here mm1=src1 mm3=begin of NEWsrc3    mm7=end of NEWsrc3
  447. por mm3,mm7 // here mm3=new src3
  448. // - 2 ----------------
  449. _ABS_DIFF_HORIZ(48)
  450. _ABS_DIFF_HORIZ(40)
  451. _ABS_DIFF_HORIZ(32)
  452. _ABS_DIFF_HORIZ(24)
  453. _ABS_DIFF_HORIZ(16)
  454. _ABS_DIFF_HORIZ(8)
  455. // - 8 ----------------
  456. movq mm5,mm1 // mm5=src1
  457. add edi, imageSize
  458. psubusb mm5,mm3 // mm5=src1-src3
  459.         psubusb mm3,mm1   // mm3=src3-src1
  460. por mm3,mm5 // mm6=|src1-src3|
  461.         movq    [edi], mm3  
  462. // -------------------------------------------------------------
  463.   // 
  464.         add edx,8     
  465. sub edi, back_step2
  466.         add edi,8
  467.         dec ecx      
  468.         jnz inner_loop    
  469.         emms   
  470.   }
  471.   return 1;
  472. }
  473. // ----------------------
  474. // FULL IMAGE, BEST ONLY : Keith's code
  475. inline int findMinimumCorrelation_mmx(
  476. const unsigned char *CurrentCorrelation,
  477. unsigned char CurrentDisparity,
  478. unsigned char *Disparity,
  479. unsigned char *BestCorrelation, int bytecount) 
  480. {
  481. if ((bytecount < 8) || ((bytecount % 8) != 0)) {
  482. return 0;
  483. }
  484. __asm {
  485. // load ecx with the pixelblock count = bytecount / 8
  486. mov ecx, bytecount
  487. shr ecx, 3
  488. // setup mm0 with 8 copies of the disparity constant
  489. mov al,  CurrentDisparity
  490. mov ah,  al
  491. mov bx,  ax
  492. shl eax,  16
  493. mov ax,  bx
  494. movd mm0,  eax
  495. movd mm1,  eax
  496. punpckldq mm0,  mm1
  497. // setup mm1 with 8 copies of the xor constant for unsigned => signed conversion
  498. mov eax, 0x80808080
  499. movd mm1, eax
  500. movd mm2, eax
  501. punpckldq mm1, mm2
  502. // setup the image pointers
  503. mov eax,  BestCorrelation
  504. mov esi,  CurrentCorrelation
  505. mov edi,  Disparity
  506. pixel_loop:
  507. movq mm2, [esi] // current correlation
  508. movq mm3, [eax] // best correlation
  509. // check for updates
  510. movq mm5, mm2 // copy the current correlation
  511. pxor mm5, mm1 // convert from unsigned range to signed range
  512. movq mm6, mm3 // copy the best correlation
  513. pxor mm6, mm1 // convert from unsigned range to signed range
  514. pcmpgtb mm5, mm6 // mm5 := (current signed> best) mask
  515. // 1 indicates current >  best, so keep best
  516. // 0 indicates current <= best, so use new value
  517. // BYPASS
  518. // this phase adds 8 additional instructions, but could skip 2 writes and 1 read
  519. // abort remainder if not updating best correlation
  520. pcmpeqb mm6, mm6 // mm6 = 0xFFFFFFFF
  521. pxor mm6,  mm5 // mm6 = mm5 xor 0xFFFFFFFF = not mm5
  522. // 0 indicates current >  best, so keep best
  523. // 1 indicates current <= best, so use new value
  524. packsswb mm6, mm6 // pack it into the lower dword of mm6 (unsigned saturation)
  525. //  11111111 11111111 => 11111111 some replaced
  526. // 11111111 00000000 => 11111111 some replaced
  527. // 00000000 11111111 => 11111111 some replaced
  528. // 00000000 00000000 => 00000000 no replacements
  529. // we don't need to backup ebx because its not used in this routine
  530. // movd mm7, ebx // make a backup of eax
  531. movd ebx, mm6 // get the saturated mask
  532. test ebx, ebx // test ebx => yields 0 iff no substitutions will occur
  533. // movd ebx, mm7 // restore ebx
  534. jz bypass // store mm4 (second correlation) to [ebx]
  535. // Update best Correlation
  536. movq mm6, mm5 // mm6 := mask
  537. movq mm7, mm5 // mm7 := mask
  538. pand mm6, mm3 // best correlation values to keep
  539. pandn mm7, mm2 // current correlation value to move to best correlation
  540. por mm6, mm7 // merge values
  541. movq [eax], mm6 // store values
  542. // update disparity
  543. movq mm2, [edi] // get disparity map
  544. movq mm6, mm5 // mm6 := mask
  545. pand mm5, mm2 // select disparity map values to keep
  546. pandn mm6, mm0 // select current disparity values to move to disparity map
  547. por mm5, mm6 // merge values
  548. movq [edi], mm5 // store values
  549. bypass:
  550. add eax, 8
  551. add esi, 8
  552. add edi, 8
  553. dec ecx
  554. jnz pixel_loop
  555. emms;
  556. }
  557. return 1;
  558. }
  559. /*int initMinimumCorrelation(
  560. const unsigned char *CurrentCorrelation,
  561. unsigned char disparityInit,
  562. unsigned char *Disparity,
  563. unsigned char *BestCorrelation,
  564. unsigned char *SecondCorrelation,
  565. int bytecount) 
  566. {
  567. for (int i=0; i<bytecount; ++i)
  568. {
  569. BestCorrelation[i]=255;
  570. SecondCorrelation[i]=255;
  571. Disparity[i]=0;
  572. }
  573. return 0;
  574. }*/
  575. inline int initMinimumCorrelation(
  576. const unsigned char *CurrentCorrelation,
  577. unsigned char disparityInit,
  578. unsigned char *Disparity,
  579. unsigned char *BestCorrelation,
  580. unsigned char *SecondCorrelation,
  581. int bytecount) 
  582. {
  583. if ((bytecount < 8) || ((bytecount % 8) != 0)) {
  584. return 0;
  585. }
  586. __asm {
  587. // setup mm0 with 8 copies of the disparity constant
  588. mov al,  disparityInit
  589. mov ah,  al
  590. mov bx,  ax
  591. shl eax,  16
  592. mov ax,  bx
  593. movd mm0,  eax
  594. movd mm1,  eax
  595. punpckldq mm0,  mm1
  596. // load ecx with the pixelblock count = bytecount / 8
  597. mov ecx, bytecount
  598. shr ecx, 3
  599. mov eax,  BestCorrelation
  600. mov ebx,  SecondCorrelation
  601. mov esi,  CurrentCorrelation
  602. mov edx, Disparity
  603. pixel_loop:
  604. movq mm1, [esi]
  605. movq [eax], mm1 // Best = Current
  606. movq [ebx], mm1 // Second = Current
  607. movq [edx], mm0 // Disparity = disparityInit
  608. add eax, 8
  609. add ebx, 8
  610. add edx, 8
  611. add esi, 8
  612. dec ecx
  613. jnz pixel_loop
  614. jmp done
  615. done:
  616. emms;
  617. }
  618. }
  619. inline int findMinimumCorrelation(
  620. const unsigned char *CurrentCorrelation,
  621. unsigned char CurrentDisparity,
  622. unsigned char *Disparity,
  623. unsigned char *BestCorrelation,
  624. unsigned char *SecondCorrelation,
  625. int bytecount) 
  626. {
  627. for (int i=0; i<bytecount; ++i,++CurrentCorrelation,++Disparity,++BestCorrelation, ++SecondCorrelation) 
  628. {
  629. if (*CurrentCorrelation<*BestCorrelation) {
  630. *Disparity = CurrentDisparity;
  631. *SecondCorrelation = *BestCorrelation;
  632. *BestCorrelation = *CurrentCorrelation;
  633. }
  634. }
  635. return 1;
  636. }
  637. // ----------------------
  638. // FULL IMAGE, BEST+SECOND .. Keith's code
  639. inline int findMinimumCorrelation_mmx(
  640. const unsigned char *CurrentCorrelation,
  641. unsigned char CurrentDisparity,
  642. unsigned char *Disparity,
  643. unsigned char *BestCorrelation,
  644. unsigned char *SecondCorrelation,
  645. int bytecount) 
  646. {
  647. if ((bytecount < 8) || ((bytecount % 8) != 0)) {
  648. return 0;
  649. }
  650. __asm {
  651. // load ecx with the pixelblock count = bytecount / 8
  652. mov ecx, bytecount
  653. shr ecx, 3
  654. // setup mm0 with 8 copies of the disparity constant
  655. mov al,  CurrentDisparity
  656. mov ah,  al
  657. mov bx,  ax
  658. shl eax,  16
  659. mov ax,  bx
  660. movd mm0,  eax
  661. movd mm1,  eax
  662. punpckldq mm0,  mm1
  663. // setup mm1 with 8 copies of the xor constant for unsigned => signed conversion
  664. mov eax, 0x80808080
  665. movd mm1, eax
  666. movd mm2, eax
  667. punpckldq mm1, mm2
  668. // setup the image pointers
  669. mov eax,  BestCorrelation
  670. mov ebx,  SecondCorrelation
  671. mov esi,  CurrentCorrelation
  672. mov edi,  Disparity
  673. pixel_loop:
  674. movq mm2, [esi] // current correlation
  675. movq mm4, [ebx] // second correlation
  676. // convert the current correlation from unsigned range to signed range
  677. movq mm5, mm2 // copy the current correlation
  678. pxor mm5, mm1 // convert from unsigned range to signed range
  679. movq mm7, mm5 // copy converted to mm7
  680. // check for second correlation updates
  681. movq mm6, mm4 // copy second best correlation
  682. pxor mm6, mm1 // convert from unsigned range to signed range
  683. pcmpgtb mm7, mm6 // mm7 := (current signed> second best) mask
  684. // BYPASS 1
  685. // skip remainder if second correlation is not to be updated
  686. // this phase adds an addition 8 instructions, but it could save as 1 memory read and 3 writes
  687. pcmpeqb mm6, mm6 // mm6 = 0xFFFFFFFF
  688. pxor mm6,  mm7 // mm6 = mm7 xor 0xFFFFFFFF = not mm7
  689. // 0 indicates current >  second, so keep old value
  690. // 1 indicates current <= second, so use new value
  691. packsswb mm6, mm6 // pack it into the lower dword of mm6 (unsigned saturation)
  692. //  11111111 11111111 => 11111111 some replaced
  693. // 11111111 00000000 => 11111111 some replaced
  694. // 00000000 11111111 => 11111111 some replaced
  695. // 00000000 00000000 => 00000000 no replacements
  696. // don't need to backup edx because its not used in this routine
  697. // movd mm3, edx // make a backup of edx
  698. movd edx, mm6 // get the saturated mask
  699. test edx, edx // test edx => yields 0 iff no replacements will occur
  700. // movd edx, mm3 // restore edx
  701. jz bypass1
  702. // direct update second correlation (get values from current)
  703. // mm7 already has mask
  704. // movq mm6, mm7 // mm6 := mask
  705. // pand mm6, mm4 // second correlation values to keep
  706. // pandn mm7, mm2 // current correlation values to move to second correlation
  707. // por mm6, mm7 // merge value => direct updated second correlation
  708. // movq mm4, mm6 // store values (*** this instruction could be eliminated!) 
  709. pand mm4, mm7 // second correlation values to keep
  710. pandn mm7, mm2 // current correlation values to move to second correlation
  711. por mm4, mm7 // merge value => direct updated second correlation
  712. // check for best correlation updates
  713. movq mm3, [eax] // best correlation
  714. // mm5 has converted current correlation
  715. movq mm6, mm3 // copy the best correlation
  716. pxor mm6, mm1 // convert from unsigned range to signed range
  717. pcmpgtb mm5, mm6 // mm5 := (current signed> best) mask
  718. // 1 indicates current >  best, so keep best
  719. // 0 indicates current <= best, so use new value
  720. // BYPASS 2
  721. // this phase adds 8 additional instructions, but could skip 2 writes and 1 read
  722. // abort remainder if not updating best correlation
  723. pcmpeqb mm6, mm6 // mm6 = 0xFFFFFFFF
  724. pxor mm6,  mm5 // mm6 = mm5 xor 0xFFFFFFFF = not mm5
  725. // 0 indicates current >  best, so keep best
  726. // 1 indicates current <= best, so use new value
  727. packsswb mm6, mm6 // pack it into the lower dword of mm6 (unsigned saturation)
  728. //  11111111 11111111 => 11111111 some replaced
  729. // 11111111 00000000 => 11111111 some replaced
  730. // 00000000 11111111 => 11111111 some replaced
  731. // 00000000 00000000 => 00000000 no replacements
  732. // don't need to backup edx because its not used in this routine
  733. // movd mm7, edx // make a backup of edx
  734. movd edx, mm6 // get the saturated mask
  735. test edx, edx // test edx => yields 0 iff no substitutions will occur
  736. // movd edx, mm7 // restore edx
  737. jz bypass2 // store mm4 (second correlation) to [ebx]
  738. // indirect update second correlation (pushed down from best)
  739. movq mm6, mm5 // mm6 := mask
  740. movq mm7, mm5 // mm7 := mask
  741. pand mm6, mm4 // second correlation values to keep
  742. pandn mm7, mm3 // best correlations to move to second correlation
  743. por mm6, mm7 // merge values
  744. movq [ebx], mm6 // store values
  745. // direct Update best Correlation
  746. movq mm6, mm5 // mm6 := mask
  747. movq mm7, mm5 // mm7 := mask
  748. pand mm6, mm3 // best correlation values to keep
  749. pandn mm7, mm2 // current correlation value to move to best correlation
  750. por mm6, mm7 // merge values
  751. movq [eax], mm6 // store values
  752. // update disparity
  753. movq mm2, [edi] // get disparity map
  754. movq mm6, mm5 // mm6 := mask
  755. pand mm5, mm2 // select disparity map values to keep
  756. pandn mm6, mm0 // select current disparity values to move to disparity map
  757. por mm5, mm6 // merge values
  758. movq [edi], mm5 // store values
  759. bypass1:
  760. next_pixel:
  761. add eax, 8
  762. add ebx, 8
  763. add esi, 8
  764. add edi, 8
  765. dec ecx
  766. jnz pixel_loop
  767. jmp done
  768. bypass2:
  769. movq [ebx], mm4;
  770. jmp next_pixel
  771. done:
  772. emms;
  773. }
  774. return 1;
  775. }
  776. inline void sum_Row(uchar* im, unsigned short* im_out, int rowSize, int maskSize) 
  777. {
  778. im += maskSize/2;
  779. im_out += maskSize/2;
  780. for (int i=0; i<rowSize; ++i) {
  781. int s=0;
  782. for (int j=-maskSize/2; j<=maskSize/2; ++j) {
  783. s+=*(im+j);
  784. }
  785. *im_out=s/maskSize;
  786. ++im;++im_out;
  787. }
  788. }
  789. inline void sum_Row_mmx(uchar* im, unsigned short* im_out, int rowSize, int maskSize) 
  790. {
  791. sum_Row_5_mmx(im, im_out, rowSize);
  792. for (int i=0; i<(maskSize-5)/2; ++i)
  793. sum_Row_5_mmx(im_out, im_out, rowSize);
  794. }
  795. inline  void sum_Row_mmx(unsigned short* im, unsigned short* im_out, int rowSize, int maskSize) 
  796. {
  797. sum_Row_5_mmx(im, im_out, rowSize);
  798. for (int i=0; i<(maskSize-5)/2; ++i)
  799. sum_Row_5_mmx(im_out, im_out, rowSize);
  800. }
  801. #define aim_Sum_Words_In_MM1 __asm 
  802. {
  803. __asm movq mm4, mm1 
  804. __asm movq mm2, mm1 
  805. __asm movq mm3, mm1 
  806. __asm psllq mm1, 16 
  807. __asm psrlq mm2, 16 
  808. __asm paddw mm4, mm2 
  809. __asm paddw mm3, mm1 
  810. __asm psrlq mm2, 16 
  811. __asm psllq mm1, 16 
  812. __asm paddw mm4, mm2 
  813. __asm psrlq mm2, 16 
  814. __asm paddw mm3, mm1 
  815. __asm psllq mm1, 16 
  816. __asm paddw mm4, mm2 
  817. __asm paddw mm3, mm1 
  818. }
  819. // apply the mask [1 1 1 1 1] to the 1-D array im (bytes)
  820. // output : im_out (words)
  821. inline void sum_Row_5_mmx(uchar* im, unsigned short* im_out, int rowSize) 
  822. {
  823. // temp: for debugging
  824. //return sum_Row_5(im,im_out,rowSize);
  825. __asm {
  826. mov eax, rowSize
  827. mov ebx, im
  828. mov ecx, im_out
  829. pxor mm6, mm6 // mm6 = x00000000
  830. //Process the first quad word, but save only the second result" 
  831. test eax, eax // Is there anything to do?" 
  832. jz end_sum_loop // Jump out if necessary 
  833. //Process low word 
  834. movq mm1, [ebx] // Copy... 
  835. punpcklbw mm1, mm6 // Expand low word bytes into words // mm1 =[D C B A]
  836. aim_Sum_Words_In_MM1
  837. //Store the result Only in the accumulator 
  838. movq mm7, mm4 // Update accumulator    mm4=[D  C+D   B+C+D   A+B+C+D]
  839. //Process high word 
  840. movq mm1, [ebx] // Copy... 
  841. punpckhbw mm1, mm6 // Expand high word bytes into words   // mm1 =[H G F E]
  842. add ebx, 8 // Update input pointer 
  843.     aim_Sum_Words_In_MM1
  844. //Add to the previous data ... 
  845. // mm3=[E+F+G+H  E+F+G  E+F   E]
  846. // mm4=[H G+H    F+G+H   E+F+G+H]
  847. paddw mm7, mm3 // The current word of the accum   // mm7=[D+E+F+G+H  C+D+E+F+G  B+C+D+E+F  A+B+C+D+E]
  848. // translate everything to 2 words on the left
  849. movq mm1, mm7 // mm1 = [D+E+F+G+H  C+D+E+F+G  B+C+D+E+F  A+B+C+D+E]
  850. psrlq   mm1, 32 // mm1 = [0  0  D+E+F+G+H  C+D+E+F+G]
  851. movq mm0, mm1 // mm0 = [D+E+F+G+H  C+D+E+F+G]
  852. psllq mm7, 32 // mm7 = [B+C+D+E+F  A+B+C+D+E  0   0]
  853. movq [ecx], mm7 // Store the final result 
  854. add ecx, 8 // Update output pointer 
  855. movq mm7, mm4 // Update accumulator    mm4=[H G+H    F+G+H   E+F+G+H]
  856. sub eax, 8 // Update the number of points left 
  857. // Start the loop 
  858. row_sum_loop:
  859. test eax, eax // Is there anything to do? 
  860. jz end_sum_loop // Jump out if necessary 
  861. movq mm1, [ebx] // Load data 
  862. //Process low word 
  863. punpcklbw mm1, mm6 // Expand low word bytes into words 
  864. aim_Sum_Words_In_MM1
  865. //Add to the previous data 
  866. //prefetcht1 [ecx+16]
  867. paddw mm7, mm3 // The current word of the accum 
  868. // translate everything to 2 words on the left
  869. // mm0 = [0 0 D C]  mm7 = [H G F E] ----> mm7=[0 0 H G]  [ecx]=[F E D C]
  870. punpckldq mm0, mm7 // mm0 = [F E D C]
  871. movq [ecx], mm0
  872. sub eax, 8 // Update the number of points left 
  873. movq mm0, mm4 // Update accumulator 
  874. psrlq mm7, 32 // mm7 = [0 0 H G]
  875. //Process high word 
  876. movq mm1, [ebx] // Copy... 
  877. punpckhbw mm1, mm6 // Expand high word bytes into words 
  878. aim_Sum_Words_In_MM1
  879. //Add to the previous data 
  880. paddw mm0, mm3 // The current word of the accum 
  881. // translate everything to 2 words on the left
  882. // mm7 = [0 0 D C]  mm0 = [H G F E] ----> mm0=[0 0 H G]  [ecx+8]=[F E D C]
  883. punpckldq mm7, mm0 // mm7 = [F E D C]
  884. add ebx, 8 // Update input pointer 
  885. movq [ecx+8], mm7
  886. psrlq mm0, 32 // mm0 = [0 0 H G] 
  887. movq mm7, mm4 // Update accumulator 
  888. add ecx, 16 // Update output pointer 
  889. jmp row_sum_loop // Loop 
  890. //Cleanup 
  891. end_sum_loop:
  892. emms 
  893. }
  894. }
  895. // apply the mask (1/4)*[1 1 1 1 1] to the 1-D array im (words)
  896. // output : im_out (words)
  897. inline void sum_Row_5_mmx(ushort* im, ushort* im_out, int rowSize) 
  898. {
  899. // temp: for debugging
  900. //return sum_Row_5(im,im_out,rowSize);
  901. __asm {
  902. mov eax, rowSize
  903. mov ebx, im
  904. mov ecx, im_out
  905. //Process the first quad word, but save only the second result" 
  906. test eax, eax // Is there anything to do?" 
  907. jz end_sum_loop // Jump out if necessary 
  908. movq mm1, [ebx] // Load data (4 words)
  909. add ebx, 8 // Update input pointer 
  910. //Process low word 
  911. aim_Sum_Words_In_MM1
  912. //Store the result Only in the accumulator 
  913. movq mm7, mm4 // Update accumulator 
  914. //Process high word 
  915. movq mm1, [ebx] // Copy... 
  916. aim_Sum_Words_In_MM1
  917. add ebx, 8
  918. //Add to the previous data 
  919. paddw mm7, mm3 // The current word of the accum 
  920. // translate everything to 2 words on the left
  921. movq mm1, mm7 // mm1 = [D+E+F+G+H  C+D+E+F+G  B+C+D+E+F  A+B+C+D+E]
  922. psrlq   mm1, 32 // mm1 = [0  0  D+E+F+G+H  C+D+E+F+G]
  923. movq mm0, mm1 // mm0 = [0  0  D+E+F+G+H  C+D+E+F+G]
  924. psllq mm7, 32 // mm7 = [B+C+D+E+F  A+B+C+D+E  0   0]
  925. movq [ecx], mm7 // Store the final result 
  926. movq mm7, mm4 // Update accumulator 
  927. add ecx, 8 // Update output pointer 
  928. sub eax, 8 // Update the number of points left 
  929. // Start the loop 
  930. row_sum_loop:
  931. test eax, eax // Is there anything to do? 
  932. jz end_sum_loop // Jump out if necessary 
  933. movq mm1, [ebx] // Load data 
  934. aim_Sum_Words_In_MM1
  935. //Add to the previous data 
  936. //prefetcht0 [ecx + 32]
  937. //prefetcht0 [ebx + 48]
  938. paddw mm7, mm3 // The current word of the accum 
  939. psrlw mm7, 2 // divide result by ...
  940. // translate everything to 2 words on the left
  941. // mm0 = [0 0 D C]  mm7 = [H G F E] ----> mm7 =[0 0 H G]  [ecx]=[F E D C]
  942. punpckldq mm0, mm7  // mm0 = [F E D C]
  943. movq [ecx], mm0
  944. sub eax, 8 // Update the number of points left 
  945. movq mm0, mm4 // Update accumulator 
  946. psrlq mm7, 32 // mm7 =[0 0 H G]
  947. //Process high word 
  948. movq mm1, [ebx+8] // Copy... 
  949. aim_Sum_Words_In_MM1
  950. //Add to the previous data 
  951. paddw mm0, mm3 // The current word of the accum 
  952. psrlw mm0, 2 // divide result by ...
  953. // translate everything to 2 words on the left
  954. // mm7 = [0 0 D C]  mm0 = [H G F E] ----> mm0=[0 0 H G]  [ecx+8]=[F E D C]
  955. punpckldq mm7, mm0 // mm7 = [F E D C]
  956. add ebx, 16 // Update input pointer 
  957. movq [ecx+8], mm7
  958. psrlq mm0, 32 // mm0 = [0 0 H G]
  959. movq mm7, mm4 // Update accumulator 
  960. add ecx, 16 // Update output pointer */
  961. jmp row_sum_loop // Loop 
  962. //Cleanup 
  963. end_sum_loop:
  964. emms 
  965. }
  966. }
  967. template<class T> void sum_Row_5(T* im, ushort* im_out, int rowSize)
  968. {
  969. im += 2;
  970. im_out +=2;
  971. int s = 0;
  972. for (int i=0; i<rowSize-5; ++i, ++im, ++im_out) {
  973. s = *(im-2);
  974. s += *(im-1);
  975. s += *(im);
  976. s += *(im+1);
  977. s += *(im+2);
  978. *im_out = s/5;
  979. }
  980. }
  981. inline void avg_Col(ushort* im, uchar* im_out, int dataSize, int width, int sizeMask)
  982. {
  983. int offset = width*(sizeMask/2);
  984. im += offset;
  985. im_out += offset;
  986. for (int i=0; i<dataSize-width*sizeMask; ++i, ++im, ++im_out) {
  987. int s = 0;
  988. for (int j=-sizeMask/2; j<=sizeMask/2; ++j) s += *(im+j*width);
  989. *im_out = s/(sizeMask);
  990. }
  991. }
  992. // apply vertical mask 1/16*[1 1 1 ... 1]^T to 'im'
  993. // result in 'im_out'
  994. inline void avg_Col_mmx(ushort* im, uchar* im_out, int dataSize, int width, int sizeMask)
  995. {
  996. // temp: for debugging
  997. //return avg_Col(im,im_out,dataSize,width,sizeMask);
  998. switch (sizeMask)
  999. {
  1000. case 5: avg_Col_5(im,im_out,dataSize,width);
  1001. break;
  1002. case 7: avg_Col_7(im,im_out,dataSize,width);
  1003. break;
  1004. case 9: avg_Col_9(im,im_out,dataSize,width);
  1005. break;
  1006. case 11: avg_Col_11(im,im_out,dataSize,width);
  1007. break;
  1008. case 13: avg_Col_13(im,im_out,dataSize,width);
  1009. break;
  1010. case 15: avg_Col_15(im,im_out,dataSize,width);
  1011. break;
  1012. case 17: avg_Col_17(im,im_out,dataSize,width);
  1013. break;
  1014. default: if (sizeMask<5) avg_Col_5(im,im_out,dataSize,width);
  1015.  else if (sizeMask>17) avg_Col_17(im,im_out,dataSize,width);
  1016. break;
  1017. }
  1018. }
  1019. #define macro_add __asm 
  1020. {
  1021. __asm  paddusw mm3, [edx]
  1022. __asm paddusw mm2, [edx+8]  
  1023. __asm add edx, edi
  1024. }
  1025. inline void avg_Col_5(ushort* im, uchar* im_out, int dataSize, int width)
  1026. {
  1027. __asm {
  1028. mov edi, width
  1029. shl edi, 1  // edi = 2*width
  1030. mov eax, dataSize
  1031. mov ecx, im_out
  1032. mov ebx, im
  1033. sub ebx, edi
  1034. sub ebx, edi // ebx = ebx-4*width
  1035. test eax, eax // Is there anything to do?" 
  1036. jz end_sum_loop // Jump out if necessary 
  1037. row_sum_loop:
  1038. test eax, eax // Is there anything to do? 
  1039. jz end_sum_loop // Jump out if necessary 
  1040. mov edx, ebx
  1041. add ebx, 16
  1042. // 1
  1043. movq mm3, [edx] // mm3 = 4 words of im
  1044. movq mm2, [edx+8] // mm2 = next 4 words of im
  1045. add edx, edi
  1046. macro_add
  1047. macro_add
  1048. macro_add
  1049. macro_add
  1050. // divide results by ...
  1051. psrlw mm3, 3
  1052. psrlw mm2, 3
  1053. // convert [mm2 mm3] as 8 bytes
  1054. packuswb mm3,mm2
  1055. movq [ecx], mm3
  1056. sub eax, 8 // Update the number of points left 
  1057. add ecx, 8 // Update output pointer 
  1058. jmp row_sum_loop // Loop 
  1059. //Cleanup 
  1060. end_sum_loop:
  1061. emms 
  1062. }
  1063. }
  1064. inline void avg_Col_7(ushort* im, uchar* im_out, int dataSize, int width)
  1065. {
  1066. __asm {
  1067. mov edi, width
  1068. shl edi, 1  // edi = 2*width
  1069. mov eax, dataSize
  1070. mov ecx, im_out
  1071. mov ebx, im
  1072. sub ebx, edi
  1073. sub ebx, edi
  1074. sub ebx, edi // ebx = ebx-6*width
  1075. test eax, eax // Is there anything to do?" 
  1076. jz end_sum_loop // Jump out if necessary 
  1077. row_sum_loop:
  1078. test eax, eax // Is there anything to do? 
  1079. jz end_sum_loop // Jump out if necessary 
  1080. mov edx, ebx
  1081. // 1
  1082. movq mm3, [edx] // mm3 = 4 words of im
  1083. add ebx, 16
  1084. movq mm2, [edx+8] // mm2 = next 4 words of im
  1085. add edx, edi
  1086. macro_add
  1087. macro_add
  1088. macro_add
  1089. macro_add
  1090. macro_add
  1091. macro_add
  1092. // divide results by ...
  1093. psrlw mm3, 3
  1094. psrlw mm2, 3
  1095. // convert [mm2 mm3] as 8 bytes
  1096. packuswb mm3,mm2
  1097. movq [ecx], mm3
  1098. sub eax, 8 // Update the number of points left 
  1099. add ecx, 8 // Update output pointer 
  1100. jmp row_sum_loop // Loop 
  1101. //Cleanup 
  1102. end_sum_loop:
  1103. emms 
  1104. }
  1105. }
  1106. inline void avg_Col_9(ushort* im, uchar* im_out, int dataSize, int width)
  1107. {
  1108. __asm {
  1109. mov edi, width
  1110. shl edi, 1  // edi = 2*width
  1111. mov eax, dataSize
  1112. mov ecx, im_out
  1113. mov ebx, im
  1114. sub ebx, edi
  1115. sub ebx, edi
  1116. sub ebx, edi
  1117. sub ebx, edi // ebx = ebx-8*width
  1118. test eax, eax // Is there anything to do?" 
  1119. jz end_sum_loop // Jump out if necessary 
  1120. row_sum_loop:
  1121. test eax, eax // Is there anything to do? 
  1122. jz end_sum_loop // Jump out if necessary 
  1123. mov edx, ebx
  1124. add ebx, 16
  1125. // 1
  1126. movq mm3, [edx] // mm3 = 4 words of im
  1127. movq mm2, [edx+8] // mm2 = next 4 words of im
  1128. add edx, edi
  1129. macro_add
  1130. macro_add
  1131. macro_add
  1132. macro_add
  1133. macro_add
  1134. macro_add
  1135. macro_add
  1136. macro_add
  1137. // divide results by ...
  1138. psrlw mm3, 3
  1139. psrlw mm2, 3
  1140. // convert [mm2 mm3] as 8 bytes
  1141. packuswb mm3,mm2
  1142. movq [ecx], mm3
  1143. sub eax, 8 // Update the number of points left 
  1144. add ecx, 8 // Update output pointer 
  1145. jmp row_sum_loop // Loop 
  1146. //Cleanup 
  1147. end_sum_loop:
  1148. emms 
  1149. }
  1150. }
  1151. inline void avg_Col_11(ushort* im, uchar* im_out, int dataSize, int width)
  1152. {
  1153. __asm {
  1154. mov edi, width
  1155. shl edi, 1  // edi = 2*width
  1156. mov eax, dataSize
  1157. mov ecx, im_out
  1158. mov ebx, im
  1159. sub ebx, edi
  1160. sub ebx, edi
  1161. sub ebx, edi
  1162. sub ebx, edi 
  1163. sub ebx, edi // ebx = ebx-10*width
  1164. test eax, eax // Is there anything to do?" 
  1165. jz end_sum_loop // Jump out if necessary 
  1166. row_sum_loop:
  1167. test eax, eax // Is there anything to do? 
  1168. jz end_sum_loop // Jump out if necessary 
  1169. mov edx, ebx
  1170. add ebx, 16
  1171. // 1
  1172. movq mm3, [edx] // mm3 = 4 words of im
  1173. movq mm2, [edx+8] // mm2 = next 4 words of im
  1174. add edx, edi
  1175. macro_add
  1176. macro_add
  1177. macro_add
  1178. macro_add
  1179. macro_add
  1180. macro_add
  1181. macro_add
  1182. macro_add
  1183. macro_add
  1184. macro_add
  1185. // divide results by ...
  1186. psrlw mm3, 4
  1187. psrlw mm2, 4
  1188. // convert [mm2 mm3] as 8 bytes
  1189. packuswb mm3,mm2
  1190. movq [ecx], mm3
  1191. sub eax, 8 // Update the number of points left 
  1192. add ecx, 8 // Update output pointer 
  1193. jmp row_sum_loop // Loop 
  1194. //Cleanup 
  1195. end_sum_loop:
  1196. emms 
  1197. }
  1198. }
  1199. inline void avg_Col_13(ushort* im, uchar* im_out, int dataSize, int width)
  1200. {
  1201. __asm {
  1202. mov edi, width
  1203. shl edi, 1  // edi = 2*width
  1204. mov eax, dataSize
  1205. mov ecx, im_out
  1206. mov ebx, im
  1207. sub ebx, edi
  1208. sub ebx, edi
  1209. sub ebx, edi
  1210. sub ebx, edi 
  1211. sub ebx, edi
  1212. sub ebx, edi // ebx = ebx-12*width
  1213. test eax, eax // Is there anything to do?" 
  1214. jz end_sum_loop // Jump out if necessary 
  1215. row_sum_loop:
  1216. test eax, eax // Is there anything to do? 
  1217. jz end_sum_loop // Jump out if necessary 
  1218. mov edx, ebx
  1219. add ebx, 16
  1220. // 1
  1221. movq mm3, [edx] // mm3 = 4 words of im
  1222. movq mm2, [edx+8] // mm2 = next 4 words of im
  1223. add edx, edi
  1224. macro_add
  1225. macro_add
  1226. macro_add
  1227. macro_add
  1228. macro_add
  1229. macro_add
  1230. macro_add
  1231. macro_add
  1232. macro_add
  1233. macro_add
  1234. macro_add
  1235. macro_add
  1236. // divide results by ...
  1237. psrlw mm3, 4
  1238. psrlw mm2, 4
  1239. // convert [mm2 mm3] as 8 bytes
  1240. packuswb mm3,mm2
  1241. movq [ecx], mm3
  1242. sub eax, 8 // Update the number of points left 
  1243. add ecx, 8 // Update output pointer 
  1244. jmp row_sum_loop // Loop 
  1245. //Cleanup 
  1246. end_sum_loop:
  1247. emms 
  1248. }
  1249. }
  1250. inline void avg_Col_15(ushort* im, uchar* im_out, int dataSize, int width)
  1251. {
  1252. __asm {
  1253. mov edi, width
  1254. shl edi, 1  // edi = 2*width
  1255. mov eax, dataSize
  1256. mov ecx, im_out
  1257. mov ebx, im
  1258. sub ebx, edi
  1259. sub ebx, edi
  1260. sub ebx, edi
  1261. sub ebx, edi
  1262. sub ebx, edi 
  1263. sub ebx, edi
  1264. sub ebx, edi // ebx = ebx-14*width
  1265. test eax, eax // Is there anything to do?" 
  1266. jz end_sum_loop // Jump out if necessary 
  1267. row_sum_loop:
  1268. test eax, eax // Is there anything to do? 
  1269. jz end_sum_loop // Jump out if necessary 
  1270. mov edx, ebx
  1271. add ebx, 16
  1272. // 1
  1273. movq mm3, [edx] // mm3 = 4 words of im
  1274. movq mm2, [edx+8] // mm2 = next 4 words of im
  1275. add edx, edi
  1276. macro_add
  1277. macro_add
  1278. macro_add
  1279. macro_add
  1280. macro_add
  1281. macro_add
  1282. macro_add
  1283. macro_add
  1284. macro_add
  1285. macro_add
  1286. macro_add
  1287. macro_add
  1288. macro_add
  1289. macro_add
  1290. // divide results by ...
  1291. psrlw mm3, 4
  1292. psrlw mm2, 4
  1293. // convert [mm2 mm3] as 8 bytes
  1294. packuswb mm3,mm2
  1295. movq [ecx], mm3
  1296. sub eax, 8 // Update the number of points left 
  1297. add ecx, 8 // Update output pointer 
  1298. jmp row_sum_loop // Loop 
  1299. //Cleanup 
  1300. end_sum_loop:
  1301. emms 
  1302. }
  1303. }
  1304. inline void avg_Col_17(ushort* im, uchar* im_out, int dataSize, int width)
  1305. {
  1306. __asm {
  1307. mov edi, width
  1308. shl edi, 1  // edi = 2*width
  1309. mov eax, dataSize
  1310. mov ecx, im_out
  1311. mov ebx, im
  1312. sub ebx, edi
  1313. sub ebx, edi
  1314. sub ebx, edi
  1315. sub ebx, edi
  1316. sub ebx, edi
  1317. sub ebx, edi 
  1318. sub ebx, edi
  1319. sub ebx, edi // ebx = ebx-16*width
  1320. test eax, eax // Is there anything to do?" 
  1321. jz end_sum_loop // Jump out if necessary 
  1322. row_sum_loop:
  1323. test eax, eax // Is there anything to do? 
  1324. jz end_sum_loop // Jump out if necessary 
  1325. mov edx, ebx
  1326. add ebx, 16
  1327. // 1
  1328. movq mm3, [edx] // mm3 = 4 words of im
  1329. movq mm2, [edx+8] // mm2 = next 4 words of im
  1330. add edx, edi
  1331. macro_add
  1332. macro_add
  1333. macro_add
  1334. macro_add
  1335. macro_add
  1336. macro_add
  1337. macro_add
  1338. macro_add
  1339. macro_add
  1340. macro_add
  1341. macro_add
  1342. macro_add
  1343. macro_add
  1344. macro_add
  1345. macro_add
  1346. macro_add
  1347. // divide results by ...
  1348. psrlw mm3, 4
  1349. psrlw mm2, 4
  1350. // convert [mm2 mm3] as 8 bytes
  1351. packuswb mm3,mm2
  1352. movq [ecx], mm3
  1353. sub eax, 8 // Update the number of points left 
  1354. add ecx, 8 // Update output pointer 
  1355. jmp row_sum_loop // Loop 
  1356. //Cleanup 
  1357. end_sum_loop:
  1358. emms 
  1359. }
  1360. }
  1361. inline void add_Col_5_wb(ushort* im, uchar* im_out, int dataSize, int width)
  1362. {
  1363. __asm {
  1364. mov edi, width
  1365. shl edi, 1  // edi = 2*width
  1366. mov eax, dataSize
  1367. mov ecx, im_out
  1368. mov ebx, im
  1369. sub ebx, edi
  1370. sub ebx, edi // ebx = ebx-4*width
  1371. test eax, eax // Is there anything to do?" 
  1372. jz end_sum_loop // Jump out if necessary 
  1373. row_sum_loop:
  1374. test eax, eax // Is there anything to do? 
  1375. jz end_sum_loop // Jump out if necessary 
  1376. mov edx, ebx
  1377. add ebx, 16
  1378. // 1
  1379. movq mm3, [edx] // mm3 = 4 words of im
  1380. movq mm2, [edx+8] // mm2 = next 4 words of im
  1381. add edx, edi
  1382. macro_add
  1383. macro_add
  1384. macro_add
  1385. macro_add
  1386. // save [mm2 mm3] as 8 bytes
  1387. packuswb mm3,mm2
  1388. movq [ecx], mm3
  1389. sub eax, 8 // Update the number of points left 
  1390. add ecx, 8 // Update output pointer 
  1391. jmp row_sum_loop // Loop 
  1392. //Cleanup 
  1393. end_sum_loop:
  1394. emms 
  1395. }
  1396. }
  1397. inline void add_Col_5_ww(ushort* im, ushort* im_out, int dataSize, int width)
  1398. {
  1399. __asm {
  1400. mov edi, width
  1401. shl edi, 1  // edi = 2*width
  1402. mov eax, dataSize
  1403. mov ecx, im_out
  1404. mov ebx, im
  1405. sub ebx, edi
  1406. sub ebx, edi // ebx = ebx-4*width
  1407. test eax, eax // Is there anything to do?" 
  1408. jz end_sum_loop // Jump out if necessary 
  1409. row_sum_loop:
  1410. test eax, eax // Is there anything to do? 
  1411. jz end_sum_loop // Jump out if necessary 
  1412. mov edx, ebx
  1413. add ebx, 16
  1414. // 1
  1415. movq mm3, [edx] // mm3 = 4 words of im
  1416. movq mm2, [edx+8] // mm2 = next 4 words of im
  1417. add edx, edi
  1418. macro_add
  1419. macro_add
  1420. macro_add
  1421. macro_add
  1422. // save [mm2 mm3] as words
  1423. movq [ecx], mm3
  1424. movq [ecx+8], mm2
  1425. sub eax, 8 // Update the number of points left 
  1426. add ecx, 16 // Update output pointer 
  1427. jmp row_sum_loop // Loop 
  1428. //Cleanup 
  1429. end_sum_loop:
  1430. emms 
  1431. }
  1432. }
  1433. // compare bestScores and secondScores. if second<best+'thresh' the disp.
  1434. // is set to 'valForReplacement' (usually 0)
  1435. inline void compareBestAndSecond(uchar* bestScores, uchar* secondScores, char thresh, 
  1436.   uchar undefined_val, 
  1437.   uchar* disp, int dataSize)
  1438. {
  1439. __asm {
  1440. // setup mm0 with 8 copies of 'thresh'
  1441. mov al,  thresh
  1442. mov ah,  al
  1443. mov bx,  ax
  1444. shl eax,  16
  1445. mov ax,  bx
  1446. movd mm0,  eax
  1447. movd mm1,  eax
  1448. punpckldq mm0,  mm1
  1449. // setup mm7 with 8 copies of 'valForReplacement'
  1450. mov al,  undefined_val
  1451. mov ah,  al
  1452. mov bx,  ax
  1453. shl eax,  16
  1454. mov ax,  bx
  1455. movd mm7,  eax
  1456. movd mm1,  eax
  1457. punpckldq mm7,  mm1
  1458. mov eax, dataSize
  1459. mov ebx, bestScores
  1460. mov ecx, secondScores
  1461. mov edx, disp
  1462. test eax, eax // Is there anything to do?" 
  1463. jz end_loop // Jump out if necessary 
  1464. comp_loop:
  1465. test eax, eax // Is there anything to do? 
  1466. jz end_loop // Jump out if necessary 
  1467. movq mm2, [ecx]
  1468. psubusb mm2, [ebx] // mm2 = secondScores - bestScores
  1469. movq mm3, [edx] // mm3 = disp
  1470. pcmpgtb mm2, mm0 // mm2 = 1 if mm2>thresh
  1471. //  0 otherwise
  1472. pand mm3, mm2
  1473. pandn mm2, mm7
  1474. por mm3, mm2
  1475. movq [edx], mm3
  1476. sub eax, 8 // Update the number of points left 
  1477. add ebx, 8 // Update output pointer 
  1478. add ecx, 8 
  1479. add edx, 8
  1480. jmp comp_loop // Loop 
  1481. //Cleanup 
  1482. end_loop:
  1483. emms 
  1484. }
  1485. }
  1486. // windowWidth must be multiple of 8
  1487. inline void cropImage(const uchar* imSrc, int width, int height, 
  1488.    uchar* imDest, int x0, int y0, int windowWidth, int windowHeight)
  1489. {
  1490. int w8 = windowWidth/8;
  1491. int step = width-windowWidth;
  1492. const uchar* srcNewOrigin = imSrc+x0+y0*width;
  1493. __asm {
  1494. mov ecx, windowHeight
  1495. mov edx, w8
  1496. mov eax,  srcNewOrigin
  1497. mov ebx,  imDest
  1498. pixel_loop:
  1499. movq mm1, [eax]
  1500. movq [ebx], mm1
  1501. add eax, 8
  1502. add ebx, 8
  1503. dec edx
  1504. jnz pixel_loop
  1505. mov edx, w8
  1506. add eax, step
  1507. dec ecx
  1508. jnz pixel_loop
  1509. jmp done
  1510. done:
  1511. emms;
  1512. }
  1513. }
  1514. // return the average pixel value
  1515. inline float pixelMean(const uchar* im, int imageSize)
  1516. {
  1517. int sum;
  1518. __asm {
  1519. mov ecx, imageSize
  1520. shr ecx, 3
  1521. mov eax, im
  1522. pxor mm7,mm7 // mm7 used as accumulator
  1523. pxor mm0,mm0 // mm0 = 0
  1524. pixel_loop:
  1525. movq mm1, [eax]
  1526. movq mm2,mm1
  1527. punpcklbw mm2, mm0
  1528. punpckhbw mm1, mm0
  1529. paddw mm2,mm1
  1530. movq mm1,mm2
  1531. punpcklwd mm2, mm0
  1532. punpckhwd mm1, mm0
  1533. paddd mm2,mm1
  1534. paddd mm7,mm2
  1535. add eax, 8
  1536. dec ecx
  1537. jnz pixel_loop
  1538. jmp done
  1539. done:
  1540. movd ebx, mm7
  1541. psrlq mm7, 32
  1542. movd edx, mm7
  1543. add ebx, edx
  1544. mov sum, ebx
  1545. emms
  1546. }
  1547. return sum / (float)imageSize;
  1548. }
  1549. // -------------------------------------------------------------
  1550. // apply mask:
  1551. // if mask[]=undefined_val im[]->im[]
  1552. // otherwise, im[]->mask[]
  1553. // ....... this one may not be exact :-(
  1554. inline void overrideImageMMX(uchar* im, const uchar* mask, uchar undefined_val, int imageSize)
  1555. {
  1556. __asm {
  1557. // setup mm0 with 8 copies of 'undefined_val'
  1558. mov al,  undefined_val
  1559. mov ah,  al
  1560. mov bx,  ax
  1561. shl eax,  16
  1562. mov ax,  bx
  1563. movd mm0,  eax
  1564. movd mm1,  eax
  1565. punpckldq mm0,  mm1
  1566. mov ecx, imageSize
  1567. shr ecx, 3
  1568. mov eax, im
  1569. mov ebx, mask
  1570. pixel_loop:
  1571. movq mm1, [eax]
  1572. movq mm2, [ebx]
  1573. movq mm3, mm2
  1574. pcmpeqb mm3, mm0 // mm3[] -> xFF if mm2[]==undefined_val
  1575. // -> x00 otherwise
  1576. pand mm3, mm1 // mm3[] = mm1[] if mm2[]==undefined_val
  1577. //  = x00   otherwise
  1578. por mm3, mm2
  1579. movq [eax], mm3
  1580. add eax, 8
  1581. add ebx, 8
  1582. dec ecx
  1583. jnz pixel_loop
  1584. jmp done
  1585. done:
  1586. emms
  1587. }
  1588. }
  1589. inline void overrideImage(uchar* im, const uchar* mask, uchar undefined_val, int imageSize)
  1590. {
  1591. for (int i=0; i<imageSize; ++i, ++im,++mask)
  1592. {
  1593. if (*mask != undefined_val) *im=*mask;
  1594. }
  1595. }
  1596. inline void divide( ushort* im,  uchar* div, uchar* result, int imageSize)
  1597. {
  1598. for (int i=0; i<imageSize; ++i,++im,++div,++result)
  1599. {
  1600. *result = (*div)?(uchar)(*im / *div):0;
  1601. }
  1602. }
  1603. // 5x5 sum filters
  1604. inline void sum_5x5_mmx( uchar* im, ushort* im_out, int dataSize, int width, ushort* buff)
  1605. {
  1606. sum_Row_5_mmx(im, buff, dataSize);
  1607. add_Col_5_ww(buff+2*width, im_out+2*width, dataSize-4*width , width);
  1608. }
  1609. inline void sum_5x5_mmx( uchar* im, uchar* im_out, int dataSize, int width, ushort* buff)
  1610. {
  1611. sum_Row_5_mmx(im, buff, dataSize);
  1612. add_Col_5_wb(buff+2*width, im_out+2*width, dataSize-4*width , width);
  1613. }
  1614. inline void binarize(uchar* im, uchar* im_out, uchar undefined_val, int dataSize)
  1615. {
  1616. for (int i=0; i<dataSize; ++i,++im,++im_out)
  1617. {
  1618. *im_out = (*im != undefined_val);
  1619. }
  1620. }
  1621. inline void set_undefined_to_zero(uchar* im, uchar* im_out, uchar undefined_val, int dataSize)
  1622. {
  1623. for (int i=0; i<dataSize; ++i,++im,++im_out)
  1624. {
  1625. if (*im == undefined_val) *im_out=0;
  1626. }
  1627. }
  1628. inline void set_zero_to_undefined(uchar* im, uchar* im_out, uchar undefined_val, int dataSize)
  1629. {
  1630. for (int i=0; i<dataSize; ++i,++im,++im_out)
  1631. {
  1632. if (*im == 0) *im_out=undefined_val;
  1633. }
  1634. }
  1635. inline void copyMMX(void* imDest, const void* imSrc, int dataSize)
  1636. {
  1637. __asm {
  1638. mov ecx, dataSize
  1639. shr ecx, 3
  1640. mov eax, imSrc
  1641. mov ebx, imDest
  1642. sub ebx, 8
  1643. pixel_loop:
  1644. movq mm1, [eax]
  1645. add ebx, 8
  1646. movq [ebx], mm1
  1647. add eax, 8
  1648. dec ecx
  1649. jnz pixel_loop
  1650. jmp done
  1651. done:
  1652. emms
  1653. }
  1654. }
  1655. inline void copySSE(void* imDest, const void* imSrc, int dataSize)
  1656. {
  1657. __asm {
  1658. mov ecx, dataSize
  1659. shr ecx, 4
  1660. mov eax, imSrc
  1661. mov ebx, imDest
  1662. sub ebx, 16
  1663. pixel_loop:
  1664. movdqa xmm1, [eax]
  1665. add ebx, 16
  1666. movdqa [ebx], xmm1
  1667. add eax, 16
  1668. dec ecx
  1669. jnz pixel_loop
  1670. jmp done
  1671. done:
  1672. emms
  1673. }
  1674. }
  1675. inline void setMMX(float* imDest, const float value, int dataSize)
  1676. {
  1677. __asm {
  1678. // make 4 copies of the constant 'value' in xmm0
  1679. movss xmm0, value
  1680. movss xmm1, xmm0
  1681. unpcklps xmm0, xmm1        
  1682. movlhps xmm0, xmm0
  1683. mov ecx, dataSize
  1684. shr ecx, 2
  1685. mov ebx, imDest
  1686. pixel_loop:
  1687. movaps [ebx], xmm0
  1688. add ebx, 16
  1689. dec ecx
  1690. jnz pixel_loop
  1691. jmp done
  1692. done:
  1693. emms
  1694. }
  1695. }
  1696. inline void setMMX(char* imDest, const char value, int dataSize)
  1697. {
  1698. __asm {
  1699. // setup mm0 with 8 copies of 'value'
  1700. mov al,  value
  1701. mov ah,  al
  1702. mov bx,  ax
  1703. shl eax,  16
  1704. mov ax,  bx
  1705. movd mm0,  eax
  1706. movd mm1,  eax
  1707. punpckldq mm0,  mm1
  1708. mov ecx, dataSize
  1709. shr ecx, 3
  1710. mov ebx, imDest
  1711. pixel_loop:
  1712. movq [ebx], mm0
  1713. add ebx, 8
  1714. dec ecx
  1715. jnz pixel_loop
  1716. jmp done
  1717. done:
  1718. emms
  1719. }
  1720. }
  1721. /*
  1722. void copyRGBAtoRGB(const uchar* imSrc, uchar* imred,uchar* imgreen,uchar* imblue, int dataSize)
  1723. {
  1724. __asm {
  1725. mov esi, dataSize
  1726. shr esi, 3
  1727. mov eax, imSrc
  1728. mov ebx, imred
  1729. mov ecx, imred
  1730. mov edx, imred
  1731. pixel_loop:
  1732. movq mm1, [eax]
  1733. movq [ebx], mm1
  1734. add eax, 8
  1735. add ebx, 8
  1736. add ecx, 8
  1737. add edx, 8
  1738. dec esi
  1739. jnz pixel_loop
  1740. jmp done
  1741. done:
  1742. emms
  1743. }
  1744. }*/
  1745. inline void multiply(uchar* im, float fact, int imageSize)
  1746. {
  1747. __asm {
  1748. mov ecx, imageSize
  1749. shr ecx, 3
  1750. // make 4 copies of the constant 'fact' in xmm0
  1751. movss xmm0, fact
  1752. movss xmm1, xmm0
  1753. unpcklps xmm0, xmm1        
  1754. movlhps xmm0, xmm0
  1755. mov eax, im
  1756. pxor mm7,mm7 // mm7 = 0 
  1757. pixel_loop:
  1758. movq mm1, [eax]
  1759. movq mm2, mm1
  1760. punpcklbw mm2, mm0
  1761. punpckhbw mm1, mm0
  1762. movq mm3,mm2
  1763. punpckhwd mm3, mm0
  1764. punpcklwd mm2, mm0
  1765. movq mm4,mm1
  1766. punpcklwd mm4, mm0
  1767. punpckhwd mm1, mm0
  1768. // here, the first 8 bytes are in d-words [mm1 mm4 mm3 mm2]
  1769. // --------
  1770. cvtpi2ps xmm3, mm3 // put mm3 in low part of xmm3
  1771. cvtpi2ps xmm2, mm2 // put mm2 in low part of xmm2
  1772. movlhps xmm2, xmm3 // xmm2 = [xmm3(low part) xmm2(low part)]
  1773. mulps xmm2, xmm0
  1774. cvtps2pi mm2, xmm2 // convert low 2 floats from xmm2 to mm2
  1775. movhlps xmm3,xmm2 // mov high 2 floats from xmm2 to low 2 floats in xmm3
  1776. cvtps2pi mm3, xmm3 // convert low 2 floats from xmm3 to mm3
  1777. packssdw mm2, mm3 // mm2 = (word)[mm2 mm3]
  1778. // --------
  1779. cvtpi2ps xmm4, mm4
  1780. cvtpi2ps xmm1, mm1
  1781. movlhps xmm4, xmm1
  1782. mulps xmm4, xmm0
  1783. cvtps2pi mm4, xmm4 // convert low 2 floats from xmm4 to mm4
  1784. movhlps xmm1,xmm4 // mov high 2 floats from xmm4 to low 2 floats in xmm1
  1785. cvtps2pi mm1, xmm1 // convert low 2 floats from xmm1 to mm1
  1786. packssdw mm4, mm1 // mm4 = (word)[mm1 mm4]
  1787. // ------
  1788. packuswb mm2, mm4 // mm2 = [[mm4] [mm2]] = [mm1 mm4 mm2 mm3]
  1789. movq [eax], mm2
  1790. add eax, 8
  1791. dec ecx
  1792. jnz pixel_loop
  1793. jmp done
  1794. done:
  1795. emms
  1796. }
  1797. }
  1798. inline void multiply(const uchar* imSrc, uchar* imDest, float fact, int imageSize)
  1799. {
  1800. __asm {
  1801. mov ecx, imageSize
  1802. shr ecx, 3
  1803. // make 4 copies of the constant 'fact' in xmm0
  1804. movss xmm0, fact
  1805. movss xmm1, xmm0
  1806. unpcklps xmm0, xmm1        
  1807. movlhps xmm0, xmm0
  1808. mov eax, imSrc
  1809. mov ebx, imDest
  1810. pxor mm7,mm7 // mm7 = 0 
  1811. pixel_loop:
  1812. movq mm1, [eax]
  1813. movq mm2, mm1
  1814. punpcklbw mm2, mm0
  1815. punpckhbw mm1, mm0
  1816. movq mm3,mm2
  1817. punpckhwd mm3, mm0
  1818. punpcklwd mm2, mm0
  1819. movq mm4,mm1
  1820. punpcklwd mm4, mm0
  1821. punpckhwd mm1, mm0
  1822. // here, the first 8 bytes are in d-words [mm1 mm4 mm3 mm2]
  1823. // --------
  1824. cvtpi2ps xmm3, mm3 // put mm3 in low part of xmm3
  1825. cvtpi2ps xmm2, mm2 // put mm2 in low part of xmm2
  1826. movlhps xmm2, xmm3 // xmm2 = [xmm3(low part) xmm2(low part)]
  1827. mulps xmm2, xmm0
  1828. cvtps2pi mm2, xmm2 // convert low 2 floats from xmm2 to mm2
  1829. movhlps xmm3,xmm2 // mov high 2 floats from xmm2 to low 2 floats in xmm3
  1830. cvtps2pi mm3, xmm3 // convert low 2 floats from xmm3 to mm3
  1831. packssdw mm2, mm3 // mm2 = (word)[mm2 mm3]
  1832. // --------
  1833. cvtpi2ps xmm4, mm4
  1834. cvtpi2ps xmm1, mm1
  1835. movlhps xmm4, xmm1
  1836. mulps xmm4, xmm0
  1837. cvtps2pi mm4, xmm4 // convert low 2 floats from xmm4 to mm4
  1838. movhlps xmm1,xmm4 // mov high 2 floats from xmm4 to low 2 floats in xmm1
  1839. cvtps2pi mm1, xmm1 // convert low 2 floats from xmm1 to mm1
  1840. packssdw mm4, mm1 // mm4 = (word)[mm1 mm4]
  1841. // ------
  1842. packuswb mm2, mm4 // mm2 = [[mm4] [mm2]] = [mm1 mm4 mm2 mm3]
  1843. movq [ebx], mm2
  1844. add eax, 8
  1845. add ebx, 8
  1846. dec ecx
  1847. jnz pixel_loop
  1848. jmp done
  1849. done:
  1850. emms
  1851. }
  1852. }