grayi.cpp
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:45k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*************************************************************************
  2. This software module was originally developed by 
  3. Ming-Chieh Lee (mingcl@microsoft.com), Microsoft Corporation
  4. Wei-ge Chen (wchen@microsoft.com), Microsoft Corporation
  5. Bruce Lin (blin@microsoft.com), Microsoft Corporation
  6. Chuang Gu (chuanggu@microsoft.com), Microsoft Corporation
  7. (date: March, 1996)
  8. in the course of development of the MPEG-4 Video (ISO/IEC 14496-2). 
  9. This software module is an implementation of a part of one or more MPEG-4 Video tools 
  10. as specified by the MPEG-4 Video. 
  11. ISO/IEC gives users of the MPEG-4 Video free license to this software module or modifications 
  12. thereof for use in hardware or software products claiming conformance to the MPEG-4 Video. 
  13. Those intending to use this software module in hardware or software products are advised that its use may infringe existing patents. 
  14. The original developer of this software module and his/her company, 
  15. the subsequent editors and their companies, 
  16. and ISO/IEC have no liability for use of this software module or modifications thereof in an implementation. 
  17. Copyright is not released for non MPEG-4 Video conforming products. 
  18. Microsoft retains full right to use the code for his/her own purpose, 
  19. assign or donate the code to a third party and to inhibit third parties from using the code for non <MPEG standard> conforming products. 
  20. This copyright notice must be included in all copies or derivative works. 
  21. Copyright (c) 1996, 1997.
  22. Module Name:
  23. grayf.hpp
  24. Abstract:
  25. Float image class for gray (one-plane) pictures 
  26. Revision History:
  27. *************************************************************************/
  28. #include <stdlib.h>
  29. #include <math.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include "typeapi.h"
  33. #ifdef __MFC_
  34. #ifdef _DEBUG
  35. #undef THIS_FILE
  36. static char BASED_CODE THIS_FILE[] = __FILE__;
  37. #endif
  38. #define new DEBUG_NEW    
  39. #endif // __MFC_
  40. CIntImage::~CIntImage ()
  41. {
  42. delete [] m_ppxli;
  43. m_ppxli = NULL;
  44. }
  45. Void CIntImage::allocate (const CRct& r, PixelI pxli) 
  46. {
  47. m_rc = r;
  48. delete [] m_ppxli, m_ppxli = NULL;
  49. // allocate pixels and initialize
  50. if (m_rc.empty ()) return;
  51. m_ppxli = new PixelI [m_rc.area ()];
  52. assert (m_ppxli);
  53. for (UInt ic = 0; ic < where ().area (); ic++)
  54. m_ppxli [ic] = pxli;
  55. }
  56. Void CIntImage::allocate (const CRct& r) 
  57. {
  58. m_rc = r;
  59. delete [] m_ppxli, m_ppxli = NULL;
  60. // allocate pixels and initialize
  61. if (m_rc.empty ()) return;
  62. m_ppxli = new PixelI [m_rc.area ()];
  63. assert (m_ppxli);
  64. }
  65. Void CIntImage::copyConstruct (const CIntImage& ii, const CRct& rct) 
  66. {
  67. CRct r = rct;
  68. if (!r.valid()) 
  69. r = ii.where ();
  70. if (!ii.valid () || (!ii.m_rc.empty () && ii.m_ppxli == NULL))
  71. assert (FALSE);
  72. allocate (r, (PixelI) 0);
  73. if (!valid ()) return; 
  74. // Copy data
  75. if (r == ii.where ())
  76. memcpy (m_ppxli, ii.pixels (), m_rc.area () * sizeof (PixelI));
  77. else {
  78. r.clip (ii.where ()); // find the intersection
  79. CoordI x = r.left; // copy pixels
  80. Int cbLine = r.width * sizeof (PixelI);
  81. PixelI* ppxl = (PixelI*) pixels (x, r.top);
  82. const PixelI* ppxlFi = ii.pixels (x, r.top);
  83. Int widthCurr = where ().width;
  84. Int widthFi = ii.where ().width;
  85. for (CoordI y = r.top; y < r.bottom; y++) {
  86. memcpy (ppxl, ppxlFi, cbLine);
  87. ppxl += widthCurr;
  88. ppxlFi += widthFi;
  89. }
  90. }
  91. }
  92. Void CIntImage::swap (CIntImage& ii) 
  93. {
  94. assert (this && &ii);
  95. CRct rcT = ii.m_rc; 
  96. ii.m_rc = m_rc; 
  97. m_rc = rcT; 
  98. PixelI* ppxliT = ii.m_ppxli; 
  99. ii.m_ppxli = m_ppxli; 
  100. m_ppxli = ppxliT; 
  101. }
  102. CIntImage::CIntImage (const CIntImage& ii, const CRct& r) : m_ppxli (NULL)
  103. {
  104. copyConstruct (ii, r);
  105. }
  106. CIntImage::CIntImage (const CRct& r, PixelI px) : m_ppxli (NULL)
  107. {
  108. allocate (r, px);
  109. }
  110. CIntImage::CIntImage (const CVideoObjectPlane& vop, RGBA comp) : m_ppxli (NULL)
  111. {
  112. if (!vop.valid ()) return;
  113. allocate (vop.where ());
  114. const CPixel* ppxl = vop.pixels ();
  115. for (UInt ip = 0; ip < where ().area (); ip++)
  116. m_ppxli [ip] = ppxl [ip].pxlU.color [comp];
  117. }
  118. CIntImage::CIntImage (
  119. const Char* pchFileName, 
  120. UInt ifr,
  121. const CRct& rct,
  122. UInt nszHeader
  123. ) : m_ppxli (NULL), m_rc (rct)
  124. {
  125. assert (!rct.empty ());
  126. allocate (rct);
  127. UInt uiArea = rct.area ();
  128. // read data from a file
  129. FILE* fpSrc = fopen (pchFileName, "rb");
  130. assert (fpSrc != NULL);
  131. fseek (fpSrc, nszHeader + ifr * sizeof (U8) * uiArea, SEEK_SET);
  132. for (UInt ip = 0; ip < uiArea; ip++)
  133. m_ppxli [ip] = getc (fpSrc);
  134. fclose (fpSrc);
  135. }
  136. CIntImage::CIntImage (const Char* vdlFileName) : m_ppxli (NULL)// read from a VM file.
  137. {
  138. CVideoObjectPlane vop (vdlFileName);
  139. allocate (vop.where ());
  140. const CPixel* ppxl = vop.pixels ();
  141. for (UInt ip = 0; ip < where ().area (); ip++)
  142. m_ppxli [ip] = ppxl [ip].pxlU.rgb.r;
  143. }
  144. Void CIntImage::where (const CRct& r) 
  145. {
  146. if (!valid ()) return; 
  147. if (where () == r) return; 
  148. CIntImage* pii = new CIntImage (*this, r);
  149. swap (*pii);
  150. delete pii;
  151. }
  152. CRct CIntImage::boundingBox (const PixelI pxliOutsideColor) const
  153. {
  154. if (allValue ((PixelI) pxliOutsideColor))
  155. return CRct ();
  156. CoordI left = where ().right - 1;
  157. CoordI top = where ().bottom - 1;
  158. CoordI right = where ().left;
  159. CoordI bottom = where ().top;
  160. const PixelI* ppxliThis = pixels ();
  161. for (CoordI y = where ().top; y < where ().bottom; y++) {
  162. for (CoordI x = where ().left; x < where ().right; x++) {
  163. if (*ppxliThis != (PixelI) pxliOutsideColor) {
  164. left = min (left, x);
  165. top = min (top, y);
  166. right = max (right, x);
  167. bottom = max (bottom, y);
  168. }
  169. ppxliThis++;
  170. }
  171. }
  172. right++;
  173. bottom++;
  174. return (CRct (left, top, right, bottom));
  175. }
  176. Int CIntImage::mean () const
  177. {
  178. if (where ().empty ()) 
  179. return 0;
  180. Int meanRet = 0;
  181. PixelI* ppxli = (PixelI*) pixels ();
  182. UInt area = where ().area ();
  183. for (UInt ip = 0; ip < area; ip++)
  184. meanRet += ppxli [ip];
  185. return (Int) (meanRet / area);
  186. }
  187. Int CIntImage::mean (const CIntImage* piiMsk) const
  188. {
  189. assert (where () == piiMsk -> where ()); // no compute if rects are different
  190. if (where ().empty ()) return 0;
  191. Int meanRet = 0;
  192. PixelI* ppxli = (PixelI*) pixels ();
  193. const PixelI* ppxliMsk = piiMsk -> pixels ();
  194. UInt area = where ().area ();
  195. UInt uiNumNonTransp = 0;
  196. for (UInt ip = 0; ip < area; ip++) {
  197. if (ppxliMsk [ip] != transpValue) {
  198. uiNumNonTransp++;
  199. meanRet += ppxli [ip];
  200. }
  201. }
  202. return (Int) (meanRet / uiNumNonTransp);
  203. }
  204. Int CIntImage::sumAbs (const CRct& rct) const 
  205. {
  206. CRct rctToDo = (!rct.valid ()) ? where () : rct;
  207. Int intRet = 0;
  208. if (rctToDo == where ()) {
  209. const PixelI* ppxli = pixels ();
  210. UInt area = where ().area ();
  211. for (UInt ip = 0; ip < area; ip++, ppxli++)
  212. intRet += (*ppxli);
  213. }
  214. else {
  215. Int width = where ().width;
  216. const PixelI* ppxliRow = pixels (rct.left, rct.top);
  217. for (CoordI y = rctToDo.top; y < rctToDo.bottom; y++) {
  218. const PixelI* ppxli = ppxliRow;
  219. for (CoordI x = rctToDo.left; x < rctToDo.right; x++, ppxli++)
  220. intRet += abs (*ppxli);
  221. ppxliRow += width;
  222. }
  223. }
  224. return intRet;
  225. }
  226. Int CIntImage::sumDeviation (const CIntImage* piiMsk) const // sum of first-order deviation
  227. {
  228. Int meanPxl = mean (piiMsk);
  229. Int devRet = 0;
  230. PixelI* ppxli = (PixelI*) pixels ();
  231. const PixelI* ppxliMsk = piiMsk -> pixels ();
  232. UInt area = where ().area ();
  233. for (UInt ip = 0; ip < area; ip++) {
  234. if (ppxliMsk [ip] != transpValue)
  235. devRet += abs (meanPxl - ppxli [ip]);
  236. }
  237. return devRet;
  238. }
  239. Int CIntImage::sumDeviation () const // sum of first-order deviation
  240. {
  241. Int meanPxl = mean ();
  242. Int devRet = 0;
  243. PixelI* ppxli = (PixelI*) pixels ();
  244. UInt area = where ().area ();
  245. for (UInt ip = 0; ip < area; ip++)
  246. devRet += abs (meanPxl - ppxli [ip]);
  247. return devRet;
  248. }
  249. Bool CIntImage::allValue (Int intVl, const CRct& rct) const
  250. {
  251. CRct rctToDo = (!rct.valid ()) ? where () : rct;
  252. if (rctToDo == where ()) {
  253. const PixelI* ppxli = pixels ();
  254. UInt area = where ().area ();
  255. for (UInt ip = 0; ip < area; ip++) {
  256. if (ppxli [ip] != intVl)
  257. return FALSE;
  258. }
  259. }
  260. else {
  261. Int width = where ().width;
  262. const PixelI* ppxli = pixels (rct.left, rct.top);
  263. for (CoordI y = rctToDo.top; y < rctToDo.bottom; y++) {
  264. const PixelI* ppxliRow = ppxli;
  265. for (CoordI x = rctToDo.left; x < rctToDo.right; x++, ppxliRow++) {
  266. if (*ppxliRow != intVl)
  267. return FALSE;
  268. }
  269. ppxli += width;
  270. }
  271. }
  272. return TRUE;
  273. }
  274. Bool CIntImage::biLevel (const CRct& rct) const
  275. {
  276. CRct rctToDo = (!rct.valid ()) ? where () : rct;
  277. if (rctToDo == where ()) {
  278. const PixelI* ppxli = pixels ();
  279. UInt area = where ().area ();
  280. for (UInt ip = 0; ip < area; ip++) {
  281. if (ppxli [ip] != opaqueValue && ppxli [ip] != transpValue)
  282. return FALSE;
  283. }
  284. }
  285. else {
  286. Int width = where ().width;
  287. const PixelI* ppxli = pixels (rct.left, rct.top);
  288. for (CoordI y = rctToDo.top; y < rctToDo.bottom; y++) {
  289. const PixelI* ppxliRow = ppxli;
  290. for (CoordI x = rctToDo.left; x < rctToDo.right; x++, ppxliRow++) {
  291. if (*ppxliRow != opaqueValue && *ppxliRow != transpValue)
  292. return FALSE;
  293. }
  294. ppxli += width;
  295. }
  296. }
  297. return TRUE;
  298. }
  299. CRct CIntImage::whereVisible () const
  300. {
  301. CoordI left = where ().right - 1;
  302. CoordI top = where ().bottom - 1;
  303. CoordI right = where ().left;
  304. CoordI bottom = where ().top;
  305. const PixelI* ppxliThis = pixels ();
  306. for (CoordI y = where ().top; y < where ().bottom; y++) {
  307. for (CoordI x = where ().left; x < where ().right; x++) {
  308. if (*ppxliThis != transpValue) {
  309. left = min (left, x);
  310. top = min (top, y);
  311. right = max (right, x);
  312. bottom = max (bottom, y);
  313. }
  314. ppxliThis++;
  315. }
  316. }
  317. right++;
  318. bottom++;
  319. return CRct (left, top, right, bottom);
  320. }
  321. Bool CIntImage::atLeastOneValue (Int ucVl, const CRct& rct) const
  322. {
  323. CRct rctRegionOfInterest = (!rct.valid ()) ? where () : rct;
  324. assert (rctRegionOfInterest <= where ());
  325. if (rctRegionOfInterest == where ()) {
  326. const PixelI* ppxli = pixels ();
  327. UInt area = where ().area ();
  328. for (UInt ip = 0; ip < area; ip++) {
  329. if (ppxli [ip] == ucVl)
  330. return TRUE;
  331. }
  332. }
  333. else {
  334. Int width = where ().width;
  335. const PixelI* ppxli = pixels (rctRegionOfInterest.left, rctRegionOfInterest.top);
  336. for (CoordI y = rctRegionOfInterest.top; y < rctRegionOfInterest.bottom; y++) {
  337. const PixelI* ppxliRow = ppxli;
  338. for (CoordI x = rctRegionOfInterest.left; x < rctRegionOfInterest.right; x++, ppxliRow++) {
  339. if (*ppxliRow == ucVl)
  340. return TRUE;
  341. }
  342. ppxli += width;
  343. }
  344. }
  345. return FALSE;
  346. }
  347. UInt CIntImage::numPixelsNotValued (Int ucVl, const CRct& rct) const // number of pixels not valued vl in region rct
  348. {
  349. CRct rctInterest = (!rct.valid ()) ? where () : rct;
  350. assert (rctInterest <= where ());
  351. UInt nRet = 0;
  352. if (rctInterest == where ()) {
  353. const PixelI* ppxli = pixels ();
  354. UInt area = where ().area ();
  355. for (UInt ip = 0; ip < area; ip++) {
  356. if (ppxli [ip] != ucVl)
  357. nRet++;
  358. }
  359. }
  360. else {
  361. Int width = where ().width;
  362. const PixelI* ppxli = pixels (rctInterest.left, rctInterest.top);
  363. for (CoordI y = rctInterest.top; y < rctInterest.bottom; y++) {
  364. const PixelI* ppxliRow = ppxli;
  365. for (CoordI x = rctInterest.left; x < rctInterest.right; x++, ppxliRow++) {
  366. if (*ppxliRow != ucVl)
  367. nRet++;
  368. }
  369. ppxli += width;
  370. }
  371. }
  372. return nRet;
  373. }
  374. Void CIntImage::setRect (const CRct& rct)
  375. {
  376. assert (rct.area () == m_rc.area ());
  377. m_rc = rct;
  378. }
  379. Void CIntImage::threshold (Int ucThresh)
  380. {
  381. PixelI* ppxlThis = (PixelI*) pixels ();
  382. UInt area = where ().area ();
  383. for (UInt id = 0; id < area; id++) {
  384. if (ppxlThis [id] < ucThresh)
  385. ppxlThis [id] = 0;
  386. }
  387. }
  388. Void CIntImage::binarize (Int ucThresh)
  389. {
  390. PixelI* ppxliThis = (PixelI*) pixels ();
  391. UInt area = where ().area ();
  392. for (UInt id = 0; id < area; id++, ppxliThis) {
  393. if (*ppxliThis < ucThresh)
  394. *ppxliThis = transpValue;
  395. else
  396. *ppxliThis = opaqueValue;
  397. }
  398. }
  399. Void CIntImage::checkRange (Int ucMin, Int ucMax)
  400. {
  401. PixelI* ppxliThis = (PixelI*) pixels ();
  402. UInt area = where ().area ();
  403. for (UInt id = 0; id < area; id++, ppxliThis++)
  404. *ppxliThis = checkrange (*ppxliThis, ucMin, ucMax);
  405. }
  406. own CIntImage* CIntImage::decimate (UInt rateX, UInt rateY) const
  407. {
  408. const CoordI left = where ().left / (CoordI) rateX;
  409. const CoordI top = where ().top / (CoordI)  rateY;
  410. const CoordI right = 
  411. (where ().right >= 0) ? (where ().right + (CoordI) rateX - 1) / (CoordI) rateX :
  412. (where ().right - (CoordI) rateX + 1) / (CoordI) rateX;
  413. const CoordI bottom = 
  414. (where ().bottom >= 0) ? (where ().bottom + (CoordI) rateX - 1) / (CoordI) rateY :
  415. (where ().bottom - (CoordI) rateX + 1) / (CoordI) rateY;
  416. CIntImage* piiRet = new CIntImage (CRct (left, top, right, bottom));
  417. PixelI* ppxliRet = (PixelI*) piiRet -> pixels ();
  418. const PixelI* ppxliOrgY = pixels ();
  419. Int skipY = rateY * where ().width;
  420. for (CoordI y = top; y < bottom; y++) {
  421. const PixelI* ppxliOrgX = ppxliOrgY;
  422. for (CoordI x = left; x < right; x++) {
  423. *ppxliRet++ = *ppxliOrgX;
  424. ppxliOrgX += rateX;
  425. }
  426. ppxliOrgY += skipY;
  427. }
  428. return piiRet;
  429. }
  430. own CIntImage* CIntImage::decimateBinaryShape (UInt rateX, UInt rateY) const
  431. {
  432. const CoordI left = where ().left / (CoordI) rateX;
  433. const CoordI top = where ().top / (CoordI) rateY;
  434. Int roundR = (where ().right >= 0) ? rateX - 1 : 1 - rateX;
  435. Int roundB = (where ().bottom >= 0) ? rateY - 1 : 1 - rateY;
  436. const CoordI right = (where ().right + roundR) / (CoordI) rateX;
  437. const CoordI bottom = (where ().bottom + roundB) / (CoordI) rateY;
  438. CIntImage* piiRet = new CIntImage (CRct (left, top, right, bottom));
  439. PixelI* ppxliRet = (PixelI*) piiRet -> pixels ();
  440. const PixelI* ppxliOrgY = pixels ();
  441. Int skipY = rateY * where ().width;
  442. CoordI x, y;
  443. CoordI iXOrigLeft, iYOrigTop; //left top of a sampling square
  444. for (y = top, iYOrigTop = where().top; y < bottom; y++, iYOrigTop += rateY) {
  445. const PixelI* ppxliOrgX = ppxliOrgY;
  446. for (x = left, iXOrigLeft = where().left; x < right; x++, iXOrigLeft += rateX) {
  447. CoordI iXOrig, iYOrig; //for scanning of the sampling square
  448. const PixelI* ppxliOrigScanY = ppxliOrgX; //same
  449. *ppxliRet = transpValue;
  450. for (iYOrig = iYOrigTop; iYOrig < (iYOrigTop + (Int) rateY); iYOrig++) {
  451. if (iYOrig >= where().bottom || *ppxliRet == opaqueValue)
  452. break;
  453. const PixelI* ppxliOrigScanX = ppxliOrigScanY; //for scan also
  454. for (iXOrig = iXOrigLeft; iXOrig < (iXOrigLeft + (Int) rateX); iXOrig++) {
  455. if (iXOrig >= where().right)
  456. break;
  457. assert (*ppxliOrigScanX == transpValue || *ppxliOrigScanX == opaqueValue);
  458. if (*ppxliOrigScanX == opaqueValue) {
  459. *ppxliRet = opaqueValue;
  460. break;
  461. }
  462. ppxliOrigScanX++;
  463. }
  464. ppxliOrigScanY += where().width;
  465. }
  466. assert (*ppxliRet == transpValue || *ppxliRet == opaqueValue);
  467. ppxliRet++;
  468. ppxliOrgX += rateX;
  469. }
  470. ppxliOrgY += skipY;
  471. }
  472. return piiRet;
  473. }
  474. own CIntImage* CIntImage::zoomup (UInt rateX, UInt rateY) const
  475. {
  476. const CoordI left = where ().left * rateX; // left-top coordinate remain the same
  477. const CoordI top = where ().top * rateY;
  478. const CoordI right = where ().right * rateX;
  479. const CoordI bottom = where ().bottom * rateY;
  480. CIntImage* piiRet = new CIntImage (CRct (left, top, right, bottom));
  481. PixelI* ppxlRet = (PixelI*) piiRet -> pixels ();
  482. for (CoordI y = top; y < bottom; y++) {
  483. for (CoordI x = left; x < right; x++)
  484. *ppxlRet++ = pixel ((CoordI) (x / rateX), (CoordI) (y / rateY));
  485. }
  486. return piiRet;
  487. }
  488. own CIntImage* CIntImage::expand (UInt rateX, UInt rateY) const // expand by putting zeros in between
  489. {
  490. const CoordI left = where ().left * rateX; // left-top coordinate remain the same
  491. const CoordI top = where ().top * rateY;
  492. const CoordI right = where ().right * rateX;
  493. const CoordI bottom = where ().bottom * rateY;
  494. CIntImage* piiRet = new CIntImage (CRct (left, top, right, bottom));
  495. PixelI* ppxlRet = (PixelI*) piiRet -> pixels ();
  496. const PixelI* ppxlThis = pixels ();
  497. for (CoordI y = top; y < bottom; y++) {
  498. for (CoordI x = left; x < right; x++) {
  499. if (x % rateX == 0 && y % rateY == 0) 
  500. *ppxlRet++ = *ppxlThis++;
  501. else
  502. *ppxlRet++ = 0;
  503. }
  504. }
  505. return piiRet;
  506. }
  507. own CIntImage* CIntImage::biInterpolate () const // bilinearly interpolate the vframe
  508. {
  509. const CoordI left = where ().left << 1; // left-top coordinate remain the same
  510. const CoordI top = where ().top << 1;
  511. const CoordI right = where ().right << 1;
  512. const CoordI bottom = where ().bottom << 1;
  513. const CoordI width = right - left;
  514. CoordI x, y;
  515. CIntImage* piiRet = new CIntImage (CRct (left, top, right, bottom));
  516. PixelI* ppxliRet = (PixelI*) piiRet -> pixels ();
  517. const PixelI* ppxli = pixels ();
  518. const CoordI right1 = right - 2;
  519. for (y = top; y < bottom; y += 2) { // x-direction interpolation
  520. for (x = left; x < right1; x += 2) {
  521. *ppxliRet++ = *ppxli++;
  522. *ppxliRet++ = (*ppxli + *(ppxli - 1) + 1) >> 1;
  523. }
  524. *ppxliRet++ = *ppxli;
  525. *ppxliRet++ = *ppxli++; // the last pixel of every row do not need average
  526. ppxliRet += width;
  527. }
  528. ppxliRet = (PixelI*) piiRet -> pixels ();
  529. ppxliRet += width; // start from the second row
  530. const CoordI width2 = width << 1;
  531. const CoordI bottom1 = bottom - 1;
  532. for (x = left; x < right; x++) { // y-direction interpolation
  533. PixelI* ppxliRett = ppxliRet++;
  534. for (y = top + 1; y < bottom1; y += 2) {
  535. *ppxliRett = (*(ppxliRett - width) + *(ppxliRett + width) + 1) >> 1;
  536. ppxliRett += width2;
  537. }
  538. *ppxliRett = *(ppxliRett - width); // the last pixel of every column do not need average
  539. }
  540. return piiRet;
  541. }
  542. own CIntImage* CIntImage::downsampleForSpatialScalability () const
  543. {
  544. static Int rgiFilterVertical[13] = {2, 0, -4, -3, 5, 19, 26, 19, 5, -3, -4, 0, 2};
  545. static Int rgiFilterHorizontal[4] = {5, 11, 11, 5};
  546. Int iWidthSrc = where (). width;
  547. Int iHeightSrc = where (). height ();
  548. assert (iWidthSrc % 2 == 0 && iHeightSrc % 2 == 0);
  549. Int iWidthDst = iWidthSrc / 2;
  550. Int iHeightDst = iHeightSrc / 2;
  551. CIntImage* piiBuffer = new CIntImage (CRct (0, 0, iWidthSrc, iHeightDst));
  552. CIntImage* piiRet = new CIntImage (CRct (0, 0, iWidthDst, iHeightDst));
  553. assert (piiBuffer != NULL);
  554. assert (piiRet != NULL);
  555. //filter and downsample vertically
  556. const PixelI* ppxliSrc;
  557. const PixelI* ppxliColumnHeadSrc = pixels ();
  558. PixelI* ppxliDst = (PixelI*) piiBuffer->pixels ();
  559. PixelI* ppxliColumnHeadDst = (PixelI*) piiBuffer->pixels ();
  560. Int i, j, k;
  561. for (i = 0; i < iWidthSrc; i++) {
  562. ppxliSrc = ppxliColumnHeadSrc;
  563. ppxliDst = ppxliColumnHeadDst;
  564. for (j = 0; j < iHeightDst; j++) {
  565. k = j * 2;         
  566. const PixelI* ppxliMinusOne = ( k < 1 ) ? ppxliSrc : ppxliSrc - iWidthSrc;
  567. const PixelI* ppxliMinusTwo = ( k < 2 ) ? ppxliSrc : ppxliMinusOne - iWidthSrc;
  568. const PixelI* ppxliMinusThree = ( k < 3 ) ? ppxliSrc : ppxliMinusTwo - iWidthSrc;
  569. const PixelI* ppxliMinusFour = ( k < 4 ) ? ppxliSrc : ppxliMinusThree - iWidthSrc;
  570. const PixelI* ppxliMinusFive = ( k < 5 ) ? ppxliSrc : ppxliMinusFour - iWidthSrc;
  571. const PixelI* ppxliMinusSix = ( k < 6 ) ? ppxliSrc : ppxliMinusFive - iWidthSrc;
  572. const PixelI* ppxliPlusOne = ( k >= iHeightSrc - 1) ? ppxliSrc : ppxliSrc + iWidthSrc;
  573. const PixelI* ppxliPlusTwo = ( k >= iHeightSrc - 2) ? ppxliPlusOne : ppxliPlusOne + iWidthSrc;
  574. const PixelI* ppxliPlusThree = ( k >= iHeightSrc - 3) ? ppxliPlusTwo : ppxliPlusTwo + iWidthSrc;
  575. const PixelI* ppxliPlusFour = ( k >= iHeightSrc - 4) ? ppxliPlusThree : ppxliPlusThree + iWidthSrc;
  576. const PixelI* ppxliPlusFive = ( k >= iHeightSrc - 5) ? ppxliPlusFour : ppxliPlusFour + iWidthSrc;
  577. const PixelI* ppxliPlusSix = ( k >= iHeightSrc - 6) ? ppxliPlusFive : ppxliPlusFive + iWidthSrc;
  578. *ppxliDst = checkrange (
  579. (Int) ((*ppxliMinusSix * rgiFilterVertical [0] +
  580. *ppxliMinusFive * rgiFilterVertical [1] +
  581. *ppxliMinusFour * rgiFilterVertical [2] +
  582. *ppxliMinusThree * rgiFilterVertical [3] +
  583. *ppxliMinusTwo * rgiFilterVertical [4] +
  584. *ppxliMinusOne * rgiFilterVertical [5] +
  585. *ppxliSrc * rgiFilterVertical [6] +
  586. *ppxliPlusOne * rgiFilterVertical [7] +
  587. *ppxliPlusTwo * rgiFilterVertical [8] +
  588. *ppxliPlusThree * rgiFilterVertical [9] +
  589. *ppxliPlusFour * rgiFilterVertical [10] +
  590. *ppxliPlusFive * rgiFilterVertical [11] +
  591. *ppxliPlusSix * rgiFilterVertical [12] + 32) >> 6),
  592. 0, 255
  593. );
  594. ppxliSrc += 2 * iWidthSrc;
  595. ppxliDst += iWidthSrc;
  596. }
  597. ppxliColumnHeadSrc++;
  598. ppxliColumnHeadDst++;
  599. //filter and downsample horizontally
  600. ppxliSrc = piiBuffer->pixels ();
  601. ppxliDst = (PixelI*) piiRet->pixels ();
  602. for (j = 0; j < iHeightDst; j++) {
  603. for (i = 0; i < iWidthDst; i++) {
  604. k = i * 2;         
  605. const PixelI* ppxliMinusOne = ( k < 1 ) ? ppxliSrc : ppxliSrc - 1;
  606. const PixelI* ppxliPlusOne = ( k >= iWidthSrc - 1) ? ppxliSrc : ppxliSrc + 1;
  607. const PixelI* ppxliPlusTwo = ( k >= iWidthSrc - 2) ? ppxliSrc : ppxliSrc + 2;
  608. *ppxliDst = checkrange (
  609. (Int) ((*ppxliMinusOne * rgiFilterHorizontal [0] +
  610. *ppxliSrc * rgiFilterHorizontal [1] +
  611. *ppxliPlusOne * rgiFilterHorizontal [2] +
  612. *ppxliPlusTwo * rgiFilterHorizontal [3] + 16) >> 5),
  613. 0, 255
  614. );
  615. ppxliSrc += 2;
  616. ppxliDst++;
  617. }
  618. delete piiBuffer;
  619. return piiRet;
  620. }
  621. own CIntImage* CIntImage::upsampleForSpatialScalability () const
  622. {
  623. CRct rctDst = where () * 2;
  624. Int iWidthSrc = where (). width;
  625. Int iHeightSrc = where (). height ();
  626. Int iHeightDst = iHeightSrc * 2;
  627. CIntImage* piiBuffer = new CIntImage (CRct (where().left, rctDst.top, where().right, rctDst.bottom));
  628. CIntImage* piiRet = new CIntImage (CRct (rctDst.left, rctDst.top, rctDst.right, rctDst.bottom));
  629. //upsample vertically
  630. const PixelI* ppxliSrc;
  631. const PixelI* ppxliSrcPlusOne;
  632. const PixelI* ppxliColumnHeadSrc = pixels ();
  633. PixelI* ppxliDst;
  634. PixelI* ppxliColumnHeadDst = (PixelI*) piiBuffer->pixels ();
  635. Int i, j;
  636. for (i = 0; i < iWidthSrc; i++) {
  637. ppxliSrc = ppxliColumnHeadSrc;
  638. ppxliSrcPlusOne = ppxliSrc + iWidthSrc;
  639. ppxliDst = ppxliColumnHeadDst;
  640. for (j = 0; j < iHeightSrc; j++) {
  641. *ppxliDst = checkrange (
  642. (Int) ((*ppxliSrc * 3 + *ppxliSrcPlusOne + 2) >> 2),
  643. 0, 255
  644. );
  645. ppxliDst += iWidthSrc;
  646. *ppxliDst = checkrange ( 
  647. (Int) ((*ppxliSrc + *ppxliSrcPlusOne * 3 + 2) >> 2),
  648. 0, 255
  649. );
  650. ppxliDst += iWidthSrc;
  651. ppxliSrc += iWidthSrc;
  652. ppxliSrcPlusOne = (j >= iHeightSrc - 2) ? ppxliSrc : ppxliSrc + iWidthSrc;
  653. }
  654. ppxliColumnHeadSrc++;
  655. ppxliColumnHeadDst++;
  656. //upsample horizontally
  657. ppxliSrc = piiBuffer->pixels ();
  658. ppxliDst = (PixelI*) piiRet->pixels ();
  659. for (j = 0; j < iHeightDst; j++) {
  660. ppxliSrcPlusOne = ppxliSrc + 1;
  661. for (i = 0; i < iWidthSrc; i++) {
  662. *ppxliDst = checkrange ( 
  663. (Int) ((*ppxliSrc * 3 + *ppxliSrcPlusOne + 2) >> 2),
  664. 0, 255
  665. );
  666. ppxliDst++;
  667. *ppxliDst = checkrange ( 
  668. (Int) ((*ppxliSrc + *ppxliSrcPlusOne * 3 + 2) >> 2),
  669. 0, 255
  670. );
  671. ppxliDst++;
  672. ppxliSrc++;
  673. ppxliSrcPlusOne = (i >= iWidthSrc - 2) ? ppxliSrc : ppxliSrc + 1;
  674. }
  675. delete piiBuffer;
  676. return piiRet;
  677. }
  678. own CIntImage* CIntImage::biInterpolate (UInt accuracy) const // bilinearly interpolate the vframe
  679. {
  680. const CoordI left = where ().left * accuracy;
  681. const CoordI top = where ().top * accuracy;
  682. const CoordI right = where ().right * accuracy;
  683. const CoordI bottom = where ().bottom * accuracy;
  684. CIntImage* piiRet = new CIntImage (CRct (left, top, right, bottom));
  685. PixelI* ppxliRet = (PixelI*) piiRet -> pixels ();
  686. for (CoordI y = top; y < bottom; y++) { // x-direction interpolation
  687. for (CoordI x = left; x < right; x++) {
  688. *ppxliRet = pixel (x, y, accuracy);
  689. ppxliRet++;
  690. }
  691. }
  692. return piiRet;
  693. }
  694. own CIntImage* CIntImage::transpose () const
  695. {
  696. CRct rctDst = where ();
  697. rctDst.transpose ();
  698. CIntImage* piiDst = new CIntImage (rctDst);
  699. const PixelI* ppxlSrc = pixels ();
  700. PixelI* ppxlDstRow = (PixelI*) piiDst->pixels ();
  701. PixelI* ppxlDst;
  702. UInt height = where ().height ();
  703. for (CoordI iy = where ().top; iy < where ().bottom; iy++) {
  704. ppxlDst = ppxlDstRow;
  705. for (CoordI ix = where ().left; ix < where ().right; ix++) {
  706. *ppxlDst = *ppxlSrc++;
  707. ppxlDst += height;
  708. }
  709. ppxlDstRow++;
  710. }
  711. return piiDst;
  712. }
  713. own CIntImage* CIntImage::warp (const CAffine2D& aff) const // affine warp
  714. {
  715. CSiteD stdLeftTopWarp = aff * CSiteD (where ().left, where ().top);
  716. CSiteD stdRightTopWarp = aff * CSiteD (where ().right, where ().top);
  717. CSiteD stdLeftBottomWarp = aff * CSiteD (where ().left, where ().bottom);
  718. CSiteD stdRightBottomWarp = aff * CSiteD (where ().right, where ().bottom);
  719. CRct rctWarp (stdLeftTopWarp, stdRightTopWarp, stdLeftBottomWarp, stdRightBottomWarp);
  720. CIntImage* piiRet = new CIntImage (rctWarp);
  721. PixelI* ppxliRet = (PixelI*) piiRet -> pixels ();
  722. CAffine2D affInv = aff.inverse ();
  723. for (CoordI y = rctWarp.top; y < rctWarp.bottom; y++) {
  724. for (CoordI x = rctWarp.left; x < rctWarp.right; x++) {
  725. CSiteD src = affInv * CSiteD (x, y); 
  726. CoordI fx = (CoordI) floor (src.x); //.5 is for better truncation
  727. CoordI fy = (CoordI) floor (src.y); //.5 is for better truncation
  728. CoordI cx = (CoordI) ceil (src.x); //.5 is for better truncation
  729. CoordI cy = (CoordI) ceil (src.y); //.5 is for better truncation
  730. if (
  731. where ().includes (fx, fy) && 
  732. where ().includes (fx, cy) && 
  733. where ().includes (cx, fy) && 
  734. where ().includes (cx, cy)
  735. )
  736. *ppxliRet = pixel (src);
  737. ppxliRet++;
  738. }
  739. }
  740. return piiRet;
  741. }
  742. own CIntImage* CIntImage::warp (const CPerspective2D& persp) const // perspective warp
  743. {
  744. CSiteD src [4], dest [4];
  745. src [0] = CSiteD (where ().left, where ().top);
  746. src [1] = CSiteD (where ().right, where ().top);
  747. src [2] = CSiteD (where ().left, where ().bottom);
  748. src [3] = CSiteD (where ().right, where ().bottom);
  749. for (UInt i = 0; i < 4; i++) {
  750. dest [i] = (persp * src [i]).s;
  751. }
  752. CRct rctWarp (dest [0], dest [1], dest [2], dest [3]);
  753. CIntImage* piiRet = new CIntImage (rctWarp);
  754. PixelI* ppxliRet = (PixelI*) piiRet -> pixels ();
  755. CPerspective2D perspInv = CPerspective2D (dest, src);
  756. for (CoordI y = rctWarp.top; y != rctWarp.bottom; y++) {
  757. for (CoordI x = rctWarp.left; x != rctWarp.right; x++) {
  758. CSiteD src = (perspInv * CSiteD (x, y)).s; 
  759. CoordI fx = (CoordI) floor (src.x); //.5 is for better truncation
  760. CoordI fy = (CoordI) floor (src.y); //.5 is for better truncation
  761. CoordI cx = (CoordI) ceil (src.x); //.5 is for better truncation
  762. CoordI cy = (CoordI) ceil (src.y); //.5 is for better truncation
  763. if (
  764. where ().includes (fx, fy) && 
  765. where ().includes (fx, cy) && 
  766. where ().includes (cx, fy) && 
  767. where ().includes (cx, cy)
  768. )
  769. *ppxliRet = pixel (src);
  770. ppxliRet++;
  771. }
  772. }
  773. return piiRet;
  774. }
  775. own CIntImage* CIntImage::warp (const CPerspective2D& persp, const CRct& rctWarp) const // perspective warp
  776. {
  777. CIntImage* piiRet = new CIntImage (rctWarp);
  778. PixelI* ppxliRet = (PixelI*) piiRet -> pixels ();
  779. CPerspective2D perspInv = persp.inverse ();
  780. for (CoordI y = rctWarp.top; y != rctWarp.bottom; y++) {
  781. for (CoordI x = rctWarp.left; x != rctWarp.right; x++) {
  782. CSiteD src = (perspInv * CSiteD (x, y)).s; 
  783. CoordI fx = (CoordI) floor (src.x); //.5 is for better truncation
  784. CoordI fy = (CoordI) floor (src.y); //.5 is for better truncation
  785. CoordI cx = (CoordI) ceil (src.x); //.5 is for better truncation
  786. CoordI cy = (CoordI) ceil (src.y); //.5 is for better truncation
  787. if (
  788. where ().includes (fx, fy) && 
  789. where ().includes (fx, cy) && 
  790. where ().includes (cx, fy) && 
  791. where ().includes (cx, cy)
  792. )
  793. *ppxliRet = pixel (src);
  794. ppxliRet++;
  795. }
  796. }
  797. return piiRet;
  798. }
  799. own CIntImage* CIntImage::warp (const CPerspective2D& persp, const CRct& rctWarp, const UInt accuracy) const // perspective warp
  800. {
  801. CIntImage* piiRet = new CIntImage (rctWarp);
  802. PixelI* ppxliRet = (PixelI*) piiRet -> pixels ();
  803. for (CoordI y = rctWarp.top; y != rctWarp.bottom; y++) {
  804. for (CoordI x = rctWarp.left; x != rctWarp.right; x++) {
  805. CSite src = (persp * CSite (x, y)).s; 
  806. CoordI fx = (CoordI) floor ((CoordD) src.x / (CoordD) accuracy); //.5 is for better truncation
  807. CoordI fy = (CoordI) floor ((CoordD) src.y / (CoordD) accuracy); //.5 is for better truncation
  808. CoordI cx = (CoordI) ceil ((CoordD) src.x / (CoordD) accuracy); //.5 is for better truncation
  809. CoordI cy = (CoordI) ceil ((CoordD) src.y / (CoordD) accuracy); //.5 is for better truncation
  810. if (
  811. where ().includes (fx, fy) && 
  812. where ().includes (fx, cy) && 
  813. where ().includes (cx, fy) && 
  814. where ().includes (cx, cy)
  815. )
  816. *ppxliRet = pixel (src, accuracy);
  817. ppxliRet++;
  818. }
  819. }
  820. return piiRet;
  821. }
  822. PixelI CIntImage::pixel (CoordD x, CoordD y) const
  823. {
  824. CoordI left = (CoordI) floor (x); // find the coordinates of the four corners
  825. CoordI wLeft = where ().left, wRight1 = where ().right - 1, wTop = where ().top, wBottom1 = where ().bottom - 1;
  826. left = checkrange (left, wLeft, wRight1);
  827. CoordI right = (CoordI) ceil (x);
  828. right = checkrange (right, wLeft, wRight1);
  829. CoordI top = (CoordI) floor (y);
  830. top = checkrange (top, wTop, wBottom1);
  831. CoordI bottom = (CoordI) ceil (y);
  832. bottom = checkrange (bottom, wTop, wBottom1);
  833. const PixelI lt = pixel (left, top);
  834. const PixelI rt = pixel (right, top);
  835. const PixelI lb = pixel (left, bottom);
  836. const PixelI rb = pixel (right, bottom);
  837. const Double distX = x - left;
  838. const Double distY = y - top;
  839. Double x01 = distX * (rt - lt) + lt; // use p.59's notation (Wolberg, Digital Image Warping)
  840. Double x23 = distX * (rb - lb) + lb;
  841. PixelI pxlRet = checkrange ((Int) (x01 + (x23 - x01) * distY + .5), 0, 255);
  842. return pxlRet;
  843. }
  844. PixelI CIntImage::pixel (CoordI x, CoordI y, UInt accuracy) const // accuracy indicates the 2/4/8/16 quantization
  845. {
  846. CoordI left = (CoordI) floor ((CoordD) x / (CoordD) accuracy); // find the coordinates of the four corners
  847. CoordI wLeft = where ().left, wRight1 = where ().right - 1, wTop = where ().top, wBottom1 = where ().bottom - 1;
  848. left = checkrange (left, wLeft, wRight1);
  849. CoordI right = (CoordI) ceil ((CoordD) x / (CoordD) accuracy);
  850. right = checkrange (right, wLeft, wRight1);
  851. CoordI top = (CoordI) floor ((CoordD) y / (CoordD) accuracy);
  852. top = checkrange (top, wTop, wBottom1);
  853. CoordI bottom = (CoordI) ceil ((CoordD) y / (CoordD) accuracy);
  854. bottom = checkrange (bottom, wTop, wBottom1);
  855. const PixelI lt = pixel (left, top);
  856. const PixelI rt = pixel (right, top);
  857. const PixelI lb = pixel (left, bottom);
  858. const PixelI rb = pixel (right, bottom);
  859. const CoordI distX = x - left * accuracy;
  860. const CoordI distY = y - top * accuracy;
  861. Double x01 = distX * (rt - lt) + accuracy * lt; // use p.59's notation (Wolberg, Digital Image Warping)
  862. Double x23 = distX * (rb - lb) + accuracy * lb;
  863. PixelI pxlRet = checkrange ((Int) ((accuracy * x01 + (x23 - x01) * distY)) / (accuracy * accuracy), 0, 255);
  864. return pxlRet;
  865. }
  866. own CIntImage* CIntImage::complement () const
  867. {
  868. CIntImage* piiDst = new CIntImage (where(), (PixelI) transpValue);
  869. const PixelI* ppxliSrc = pixels ();
  870. PixelI* ppxliDst = (PixelI*) piiDst->pixels ();
  871. for (UInt iPxl = 0; iPxl < where ().area (); iPxl++)
  872. *ppxliDst++ = *ppxliSrc++ ^ 0xFF;
  873. return piiDst;
  874. }
  875. Void CIntImage::overlay (const CIntImage& ii)
  876. {
  877. if (!valid () || !ii.valid () || ii.where ().empty ()) return;
  878. CRct r = m_rc; 
  879. r.include (ii.m_rc); // overlay is defined on union of rects
  880. where (r); 
  881. if (!valid ()) return; 
  882. assert (ii.m_ppxli != NULL); 
  883. CRct rctFi = ii.m_rc;
  884. Int widthFi = rctFi.width;
  885. Int widthCurr = where ().width;
  886. PixelI* ppxliThis = (PixelI*) pixels (rctFi.left, rctFi.top);
  887. const PixelI* ppxliFi = ii.pixels ();
  888. for (CoordI y = rctFi.top; y < rctFi.bottom; y++) { // loop through VOP CRct
  889. memcpy (ppxliThis, ppxliFi, rctFi.width * sizeof (PixelI));
  890. ppxliThis += widthCurr; 
  891. ppxliFi += widthFi;
  892. }
  893. }
  894. Void CIntImage::overlay (const CFloatImage& fi)
  895. {
  896. if (!valid () || !fi.valid () || fi.where ().empty ()) return;
  897. CRct r = m_rc; 
  898. r.include (fi.where()); // overlay is defined on union of rects
  899. where (r); 
  900. if (!valid ()) return; 
  901. assert (fi.pixels() != NULL); 
  902. CRct rctFi = fi.where();
  903. PixelF fVal;
  904. Int widthFi = rctFi.width;
  905. Int widthCurr = where ().width;
  906. PixelI* ppxliThis = (PixelI*) pixels (rctFi.left, rctFi.top);
  907. const PixelF* ppxliFi = fi.pixels ();
  908. CoordI x;
  909. for (CoordI y = rctFi.top; y < rctFi.bottom; y++) { // loop through VOP CRct
  910. for(x=0;x<rctFi.width;x++)
  911. {
  912. fVal=ppxliFi[x];
  913. ppxliThis[x]=(fVal>=0)?(Int)(fVal+0.5):(Int)(fVal-0.5);
  914. }
  915. ppxliThis += widthCurr; 
  916. ppxliFi += widthFi;
  917. }
  918. }
  919. own CIntImage* CIntImage::smooth_ (UInt window) const
  920. {
  921. const UInt offset = window >> 1;
  922. const UInt offset2 = offset << 1;
  923. const UInt size = window * window; // array size to be sorted
  924. const UInt med = size >> 1;
  925. CIntImage* pfmgRet = new CIntImage (*this);
  926. // bound of the image to be filtered.
  927. const CoordI left = where ().left + offset;
  928. const CoordI top = where ().top + offset;
  929. const CoordI right = where ().right - offset;
  930. const CoordI bottom = where ().bottom - offset;
  931. const Int width = where ().width;
  932. const Int dist = offset + offset * width;
  933. const Int wwidth = width - window;
  934. PixelI* rgValues = new PixelI [size];
  935. PixelI* pRet = (PixelI*) pfmgRet -> pixels (left, top);
  936. const PixelI* p = pixels (left, top);
  937. for (CoordI y = top; y != bottom; y++) {
  938. for (CoordI x = left; x != right; x++) {
  939. const PixelI* pp = p - dist; // get correct index
  940. UInt numTransp = 0;
  941. for (UInt sy = 0; sy < window; sy++) {
  942. for (UInt sx = 0; sx < window; sx++) {
  943. if (*pp == transpValue)
  944. numTransp++;
  945. pp++;
  946. }
  947. pp += wwidth;
  948. }
  949. *pRet++ = (PixelI) ((numTransp <= med) ? opaqueValue : transpValue);
  950. p++;
  951. }
  952. pRet += offset2;
  953. p += offset2;
  954. }
  955. delete [] rgValues;
  956. return pfmgRet;
  957. }
  958. own CIntImage* CIntImage::smooth (UInt window) const
  959. {
  960. UInt offset = window >> 1;
  961. CRct rctExp (where ());
  962. rctExp.expand (offset);
  963. CIntImage* piiExp = new CIntImage (*this, rctExp);
  964. CIntImage* piiSmooth = piiExp -> smooth_ (window);
  965. piiSmooth -> where (where ());
  966. delete piiExp;
  967. return piiSmooth;
  968. }
  969. Void CIntImage::xorIi (const CIntImage& ii)
  970. {
  971. CRct rctIntersect = m_rc;
  972. rctIntersect.clip (ii.where());
  973. if (!rctIntersect.valid () || rctIntersect.empty ()) return;
  974. PixelI* ppxliRowStart1 = (PixelI*) pixels (rctIntersect.left, rctIntersect.top);
  975. const PixelI* ppxliRowStart2 = ii.pixels (rctIntersect.left, rctIntersect.top);
  976. for (CoordI iy = rctIntersect.top; iy < rctIntersect.bottom; iy++)   {
  977. PixelI* ppxli1 = ppxliRowStart1;
  978. const PixelI* ppxli2 = ppxliRowStart2;
  979. for (CoordI ix = rctIntersect.left; ix < rctIntersect.right; ix++) {
  980. assert (*ppxli1 == transpValue || *ppxli1 == opaqueValue);
  981. assert (*ppxli2 == transpValue || *ppxli2 == opaqueValue);
  982. if (*ppxli1 == *ppxli2)
  983. *ppxli1 = (PixelI) transpValue;
  984. else 
  985. *ppxli1 = (PixelI) opaqueValue;
  986. ppxli1++;
  987. ppxli2++;
  988. }
  989. ppxliRowStart1 += where().width;
  990. ppxliRowStart2 += ii.where().width;
  991. }
  992. }
  993. Void CIntImage::orIi (const CIntImage& ii)
  994. {
  995. CRct rctIntersect = m_rc;
  996. rctIntersect.clip (ii.where());
  997. if (!rctIntersect.valid () || rctIntersect.empty ()) return;
  998. PixelI* ppxliRowStart1 = (PixelI*) pixels (rctIntersect.left, rctIntersect.top);
  999. const PixelI* ppxliRowStart2 = ii.pixels (rctIntersect.left, rctIntersect.top);
  1000. for (CoordI iy = rctIntersect.top; iy < rctIntersect.bottom; iy++)   {
  1001. PixelI* ppxli1 = ppxliRowStart1;
  1002. const PixelI* ppxli2 = ppxliRowStart2;
  1003. for (CoordI ix = rctIntersect.left; ix < rctIntersect.right; ix++) {
  1004. assert (*ppxli1 == transpValue || *ppxli1 == opaqueValue);
  1005. assert (*ppxli2 == transpValue || *ppxli2 == opaqueValue);
  1006. if (*ppxli2 == opaqueValue)
  1007. *ppxli1 = opaqueValue;
  1008. ppxli1++;
  1009. ppxli2++;
  1010. }
  1011. ppxliRowStart1 += where ().width;
  1012. ppxliRowStart2 += ii.where ().width;
  1013. }
  1014. }
  1015. Void CIntImage::andIi (const CIntImage& ii)
  1016. {
  1017. CRct rctIntersect = m_rc;
  1018. rctIntersect.clip (ii.where());
  1019. if (!rctIntersect.valid () || rctIntersect.empty ()) return;
  1020. PixelI* ppxliRowStart1 = (PixelI*) pixels (rctIntersect.left, rctIntersect.top);
  1021. const PixelI* ppxliRowStart2 = ii.pixels (rctIntersect.left, rctIntersect.top);
  1022. for (CoordI iy = rctIntersect.top; iy < rctIntersect.bottom; iy++)   {
  1023. PixelI* ppxli1 = ppxliRowStart1;
  1024. const PixelI* ppxli2 = ppxliRowStart2;
  1025. for (CoordI ix = rctIntersect.left; ix < rctIntersect.right; ix++) {
  1026. assert (*ppxli1 == transpValue || *ppxli1 == opaqueValue);
  1027. assert (*ppxli2 == transpValue || *ppxli2 == opaqueValue);
  1028. if (*ppxli2 == transpValue)
  1029. *ppxli1 = transpValue;
  1030. ppxli1++;
  1031. ppxli2++;
  1032. }
  1033. ppxliRowStart1 += where().width;
  1034. ppxliRowStart2 += ii.where().width;
  1035. }
  1036. }
  1037. Void CIntImage::maskOut (const CIntImage& ii)
  1038. {
  1039. CRct rctIntersect = m_rc;
  1040. rctIntersect.clip (ii.where());
  1041. if (!rctIntersect.valid () || rctIntersect.empty ()) return;
  1042. PixelI* ppxliRowStart = (PixelI*) pixels (rctIntersect.left, rctIntersect.top);
  1043. const PixelI* ppxliRowStartMask = ii.pixels (rctIntersect.left, rctIntersect.top);
  1044. for (CoordI iy = rctIntersect.top; iy < rctIntersect.bottom; iy++)   {
  1045. PixelI* ppxli = ppxliRowStart;
  1046. const PixelI* ppxliMask = ppxliRowStartMask;
  1047. for (CoordI ix = rctIntersect.left; ix < rctIntersect.right; ix++) {
  1048. assert (*ppxliMask == transpValue || *ppxliMask == opaqueValue);
  1049. assert (*ppxli == transpValue || *ppxli == opaqueValue);
  1050. if (*ppxliMask != transpValue)
  1051. *ppxli = transpValue;
  1052. ppxli++;
  1053. ppxliMask++;
  1054. }
  1055. ppxliRowStart += where ().width;
  1056. ppxliRowStartMask += ii.where ().width;
  1057. }
  1058. }
  1059. Void CIntImage::mutiplyAlpha (const CIntImage& ii)
  1060. {
  1061. CRct rctIntersect = m_rc;
  1062. rctIntersect.clip (ii.where());
  1063. if (!rctIntersect.valid () || rctIntersect.empty ()) return;
  1064. PixelI* ppxliRowStart = (PixelI*) pixels (rctIntersect.left, rctIntersect.top);
  1065. const PixelI* ppxliRowStartMask = ii.pixels (rctIntersect.left, rctIntersect.top);
  1066. for (CoordI iy = rctIntersect.top; iy < rctIntersect.bottom; iy++)   {
  1067. PixelI* ppxli = ppxliRowStart;
  1068. const PixelI* ppxliMask = ppxliRowStartMask;
  1069. for (CoordI ix = rctIntersect.left; ix < rctIntersect.right; ix++) {
  1070. assert (*ppxliMask == transpValue || *ppxliMask == opaqueValue);
  1071. if (*ppxliMask == transpValue)
  1072. *ppxli = transpValue;
  1073. else
  1074. *ppxli = (PixelI) ((*ppxli * *ppxliMask + 127) / opaqueValueF); //normalize
  1075. ppxli++;
  1076. ppxliMask++;
  1077. }
  1078. ppxliRowStart += where ().width;
  1079. ppxliRowStartMask += ii.where ().width;
  1080. }
  1081. }
  1082. Void CIntImage::cropOnAlpha ()
  1083. {
  1084. CRct rctVisible = whereVisible ();
  1085. where (rctVisible);
  1086. }
  1087. Void CIntImage::operator = (const CIntImage& ii)
  1088. {
  1089. delete [] m_ppxli;
  1090. copyConstruct (ii, ii.where ());
  1091. }
  1092. Bool CIntImage::operator == (const CIntImage& ii) const
  1093. {
  1094. if (ii.where () != where ())
  1095. return FALSE;
  1096. UInt area = where ().area ();
  1097. const PixelI* ppxli = ii.pixels ();
  1098. const PixelI* ppxliThis = pixels ();
  1099. for (UInt ip = 0; ip < area; ip++, ppxli++, ppxliThis++)
  1100. if (*ppxli != *ppxliThis)
  1101. return FALSE;
  1102. return TRUE;
  1103. }
  1104. Double CIntImage::mse (const CIntImage& iiCompare) const
  1105. {
  1106. assert (iiCompare.where () == where ());
  1107. Int sqr = 0;
  1108. const PixelI* ppxliThis = pixels ();
  1109. const PixelI* ppxliCompare = iiCompare.pixels ();
  1110. UInt area = where ().area ();
  1111. for (UInt i = 0; i < area; i++) {
  1112. Int diffR = *ppxliThis - *ppxliCompare;
  1113. sqr += diffR * diffR;
  1114. ppxliThis++;
  1115. ppxliCompare++;
  1116. }
  1117. return ((Double) sqr / area);
  1118. }
  1119. Double CIntImage::mse (const CIntImage& iiCompare, const CIntImage& iiMsk) const
  1120. {
  1121. assert (iiCompare.where () == where () && iiMsk.where () == where ());
  1122. Int sqr = 0;
  1123. const PixelI* ppxliThis = pixels ();
  1124. const PixelI* ppxliCompare = iiCompare.pixels ();
  1125. const PixelI* ppxliMsk = iiMsk.pixels ();
  1126. UInt area = where ().area ();
  1127. UInt uiNonTransp = 0;
  1128. for (UInt i = 0; i < area; i++) {
  1129. if (*ppxliMsk != transpValue) {
  1130. Int diffR = *ppxliThis - *ppxliCompare;
  1131. sqr += diffR * diffR;
  1132. uiNonTransp++;
  1133. }
  1134. ppxliThis++;
  1135. ppxliCompare++;
  1136. ppxliMsk++;
  1137. }
  1138. if (uiNonTransp == 0) 
  1139. return 0;
  1140. return ((Double) sqr / area);
  1141. }
  1142. Double CIntImage::snr (const CIntImage& iiCompare) const
  1143. {
  1144. Double msError = (Double) mse (iiCompare);
  1145. if (msError == 0.0)
  1146. return 1000000.0;
  1147. else 
  1148. return (log10 (255 * 255 / msError) * 10.0);
  1149. }
  1150. Double CIntImage::snr (const CIntImage& iiCompare, const CIntImage& iiMsk) const
  1151. {
  1152. CIntImage* piiMskOp = NULL;
  1153. Double msError = 0;
  1154. if (&iiMsk == NULL) {
  1155. piiMskOp = new CIntImage (where (), (PixelI) opaqueValue);
  1156. msError = mse (iiCompare, *piiMskOp);
  1157. delete piiMskOp;
  1158. }
  1159. else
  1160. msError = mse (iiCompare, iiMsk);
  1161. if (msError == 0.0)
  1162. return 1000000.0;
  1163. else 
  1164. return (log10 (255 * 255 / msError) * 10.0);
  1165. }
  1166. Void CIntImage::vdlDump (const Char* fileName) const
  1167. {
  1168. CVideoObjectPlane vop (where (), opaquePixel);
  1169. CPixel* ppxl = (CPixel*) vop.pixels ();
  1170. const PixelI* ppxli = pixels ();
  1171. UInt area = where ().area ();
  1172. for (UInt ip = 0; ip < area; ip++, ppxl++, ppxli++)
  1173. *ppxl = CPixel (*ppxli, *ppxli, *ppxli, opaqueValue);
  1174. vop.vdlDump (fileName);
  1175. }
  1176. Void CIntImage::dump (FILE* pf) const
  1177. {
  1178. // was a binary write, but now reflects code in CFloatImage::dump()
  1179. //fwrite (m_ppxli, sizeof (Int), where ().area (), pf);
  1180. assert (pf != NULL);
  1181. UInt area = where ().area ();
  1182. U8* rguchPixelData = new U8 [where().area()];
  1183. U8* puch = rguchPixelData;
  1184. const PixelI* ppxli = pixels ();
  1185. for (UInt ip = 0; ip < area; ip++, puch++, ppxli++) {
  1186. U8 vl = (U8) checkrange ((Int)*ppxli, (Int)0, (Int)255);
  1187. *puch = vl;
  1188. }
  1189. fwrite (rguchPixelData, sizeof (U8), area, pf);
  1190. delete [] rguchPixelData;
  1191. }
  1192. Void CIntImage::txtDump (const Char* fileName) const
  1193. {
  1194. FILE* pfTxt;
  1195. const PixelI* ppxli = pixels ();
  1196. if (fileName != NULL)
  1197. pfTxt = fopen (fileName, "w");
  1198. else
  1199. pfTxt = NULL;
  1200. for (CoordI y = 0; y < where ().height (); y++) {
  1201. for (CoordI x = 0; x < where ().width; x++) {
  1202. if (pfTxt != NULL)
  1203. fprintf (pfTxt, "%3d  ", *ppxli);
  1204. else
  1205. printf ("%3d  ", *ppxli);
  1206. ppxli++;
  1207. }
  1208. if (pfTxt != NULL)
  1209. fprintf (pfTxt, "n");
  1210. else
  1211. printf ("n");
  1212. }
  1213. if (pfTxt != NULL)
  1214. fclose (pfTxt);
  1215. }
  1216. Void CIntImage::txtDump (FILE *pf) const
  1217. {
  1218. const PixelI *ppxli = pixels();
  1219. for (CoordI y = 0; y < where ().height (); y++) {
  1220. for (CoordI x = 0; x < where ().width; x++) {
  1221. fprintf (pf, "%3d ", *ppxli);
  1222. ppxli++;
  1223. }
  1224. fprintf (pf,"n");
  1225. }
  1226. fprintf (pf,"n");
  1227. }
  1228. Void CIntImage::txtDumpMask (FILE *pf) const
  1229. {
  1230. const PixelI *ppxli = pixels ();
  1231. for (CoordI y = 0; y < where ().height (); y++) {
  1232. for (CoordI x = 0; x < where ().width; x++) {
  1233. if (*ppxli == transpValue)
  1234. fprintf (pf, "..");
  1235. else
  1236. fprintf (pf, "[]");
  1237. ppxli++;
  1238. }
  1239. fprintf (pf,"n");
  1240. }
  1241. fprintf (pf,"n");
  1242. }
  1243. own CIntImage* CIntImage::operator + (const CIntImage& ii) const
  1244. {
  1245. if (!valid () || !ii.valid ()) return NULL;
  1246. assert (where () == ii.where ());
  1247. CIntImage* piiSumRet = new CIntImage (where ());
  1248. PixelI* ppxliRet = (PixelI*) piiSumRet -> pixels ();
  1249. const PixelI* ppxliThis = pixels ();
  1250. const PixelI* ppxliFi = ii.pixels ();
  1251. UInt area = where ().area ();
  1252. for (UInt ip = 0; ip < area; ip++, ppxliRet++, ppxliThis++, ppxliFi++)
  1253. *ppxliRet = *ppxliThis + *ppxliFi;
  1254. return piiSumRet;
  1255. }
  1256. own CIntImage* CIntImage::operator - (const CIntImage& ii) const
  1257. {
  1258. if (!valid () || !ii.valid ()) return NULL;
  1259. assert (where () == ii.where ());
  1260. CIntImage* piiSumRet = new CIntImage (where ());
  1261. PixelI* ppxliRet = (PixelI*) piiSumRet -> pixels ();
  1262. const PixelI* ppxliThis = pixels ();
  1263. const PixelI* ppxliFi = ii.pixels ();
  1264. UInt area = where ().area ();
  1265. for (UInt ip = 0; ip < area; ip++, ppxliRet++, ppxliThis++, ppxliFi++)
  1266. *ppxliRet = *ppxliThis - *ppxliFi;
  1267. return piiSumRet;
  1268. }
  1269. own CIntImage* CIntImage::operator * (Int scale) const
  1270. {
  1271. if (!valid ()) return NULL;
  1272. CIntImage* piiSumRet = new CIntImage (where ());
  1273. PixelI* ppxliRet = (PixelI*) piiSumRet -> pixels ();
  1274. const PixelI* ppxliThis = pixels ();
  1275. UInt area = where ().area ();
  1276. for (UInt ip = 0; ip < area; ip++, ppxliRet++, ppxliThis++)
  1277. *ppxliRet = *ppxliThis * scale;
  1278. return piiSumRet;
  1279. }
  1280. own CIntImage* CIntImage::operator / (Int scale) const
  1281. {
  1282. if (!valid ()) return NULL;
  1283. assert (scale != .0f);
  1284. CIntImage* piiSumRet = new CIntImage (where ());
  1285. PixelI* ppxliRet = (PixelI*) piiSumRet -> pixels ();
  1286. const PixelI* ppxliThis = pixels ();
  1287. UInt area = where ().area ();
  1288. for (UInt ip = 0; ip < area; ip++, ppxliRet++, ppxliThis++)
  1289. *ppxliRet = *ppxliThis / scale;
  1290. return piiSumRet;
  1291. }
  1292. own CIntImage* CIntImage::average (const CIntImage& ii) const
  1293. {
  1294. if (!valid () || !ii.valid ()) return NULL;
  1295. assert (where () == ii.where ());
  1296. CIntImage* piiSumRet = new CIntImage (where ());
  1297. PixelI* ppxliRet = (PixelI*) piiSumRet -> pixels ();
  1298. const PixelI* ppxliThis = pixels ();
  1299. const PixelI* ppxliFi = ii.pixels ();
  1300. UInt area = where ().area ();
  1301. for (UInt ip = 0; ip < area; ip++, ppxliRet++, ppxliThis++, ppxliFi++)
  1302. *ppxliRet = (*ppxliThis + *ppxliFi + 1) / 2;
  1303. return piiSumRet;
  1304. }