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

流媒体/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. grayc.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. #ifdef __NBIT_
  41. void pxlcmemset(PixelC *ppxlc, PixelC pxlcVal, Int iCount)
  42. {
  43. Int i;
  44. for(i=0; i<iCount;i++)
  45. ppxlc[i] = pxlcVal;
  46. }
  47. #endif
  48. CU8Image::~CU8Image ()
  49. {
  50. delete [] m_ppxlc;
  51. m_ppxlc = NULL;
  52. }
  53. Void CU8Image::allocate (const CRct& r, PixelC pxlc) 
  54. {
  55. m_rc = r;
  56. delete [] m_ppxlc, m_ppxlc = NULL;
  57. // allocate pixels and initialize
  58. if (m_rc.empty ()) return;
  59. m_ppxlc = new PixelC [m_rc.area ()];
  60. memset (m_ppxlc, pxlc, where ().area () * sizeof (PixelC));
  61. }
  62. Void CU8Image::allocate (const CRct& r) 
  63. {
  64. m_rc = r;
  65. // allocate pixels and initialize
  66. m_ppxlc = new PixelC [m_rc.area ()];
  67. assert (m_ppxlc != NULL);
  68. }
  69. Void CU8Image::copyConstruct (const CU8Image& uci, const CRct& rct) 
  70. {
  71. CRct r = rct;
  72. if (!r.valid()) 
  73. r = uci.where ();
  74. if (!uci.valid () || (!uci.m_rc.empty () && uci.m_ppxlc == NULL))
  75. assert (FALSE);
  76. allocate (r, (PixelC) 0);
  77. if (!valid ()) return; 
  78. // Copy data
  79. if (r == uci.where ())
  80. memcpy (m_ppxlc, uci.pixels (), m_rc.area () * sizeof (PixelC));
  81. else {
  82. r.clip (uci.where ()); // find the intersection
  83. CoordI x = r.left; // copy pixels
  84. Int cbLine = r.width * sizeof (PixelC);
  85. PixelC* ppxl = (PixelC*) pixels (x, r.top);
  86. const PixelC* ppxlFi = uci.pixels (x, r.top);
  87. Int widthCurr = where ().width;
  88. Int widthFi = uci.where ().width;
  89. for (CoordI y = r.top; y < r.bottom; y++) {
  90. memcpy (ppxl, ppxlFi, cbLine);
  91. ppxl += widthCurr;
  92. ppxlFi += widthFi;
  93. }
  94. }
  95. }
  96. Void CU8Image::swap (CU8Image& uci) 
  97. {
  98. assert (this && &uci);
  99. CRct rcT = uci.m_rc; 
  100. uci.m_rc = m_rc; 
  101. m_rc = rcT; 
  102. PixelC* ppxlcT = uci.m_ppxlc; 
  103. uci.m_ppxlc = m_ppxlc; 
  104. m_ppxlc = ppxlcT; 
  105. }
  106. CU8Image::CU8Image (const CU8Image& uci, const CRct& r) : m_ppxlc (NULL)
  107. {
  108. copyConstruct (uci, r);
  109. }
  110. CU8Image::CU8Image (const CRct& r, PixelC px) : m_ppxlc (NULL)
  111. {
  112. allocate (r, px);
  113. }
  114. CU8Image::CU8Image (const CRct& r) : m_ppxlc (NULL)
  115. {
  116. allocate (r);
  117. }
  118. CU8Image::CU8Image (const CVideoObjectPlane& vop, RGBA comp, const CRct& r) : m_ppxlc (NULL)
  119. {
  120. if (!vop.valid ()) return;
  121. CU8Image* puci = new CU8Image (vop.where ());
  122. PixelC* ppxlc = (PixelC*) puci -> pixels ();
  123. const CPixel* ppxl = vop.pixels ();
  124. UInt area = puci -> where ().area ();
  125. for (UInt ip = 0; ip < area; ip++, ppxl++)
  126. *ppxlc++ = (PixelC) ppxl -> pxlU.color [comp];
  127. copyConstruct (*puci, r);
  128. delete puci;
  129. }
  130. CU8Image::CU8Image (
  131. const Char* pchFileName, 
  132. UInt ifr,
  133. const CRct& rct,
  134. UInt nszHeader
  135. ) : m_ppxlc (NULL), m_rc (rct)
  136. {
  137. assert (!rct.empty ());
  138. assert (ifr >= 0);
  139. assert (nszHeader >= 0);
  140. UInt uiArea = rct.area ();
  141. delete [] m_ppxlc;
  142. m_ppxlc = new PixelC [uiArea];
  143. assert (m_ppxlc);
  144. // read data from a file
  145. FILE* fpSrc = fopen (pchFileName, "rb");
  146. assert (fpSrc != NULL);
  147. fseek (fpSrc, nszHeader + ifr * sizeof (U8) * uiArea, SEEK_SET);
  148. Int size = (Int) fread (m_ppxlc, sizeof (U8), uiArea, fpSrc);
  149. assert (size != 0);
  150. fclose (fpSrc);
  151. }
  152. CU8Image::CU8Image (const Char* vdlFileName) : m_ppxlc (NULL)// read from a VM file.
  153. {
  154. CVideoObjectPlane vop (vdlFileName);
  155. m_rc = vop.where ();
  156. UInt uiArea = where ().area ();
  157. delete [] m_ppxlc;
  158. m_ppxlc = new PixelC [uiArea];
  159. assert (m_ppxlc);
  160. const CPixel* ppxlVop = vop.pixels ();
  161. PixelC* ppxlcRet = (PixelC*) pixels ();
  162. for (UInt ip = 0; ip < uiArea; ip++, ppxlcRet++, ppxlVop++)
  163. *ppxlcRet = (PixelC) ppxlVop -> pxlU.rgb.r;
  164. }
  165. Void CU8Image::where (const CRct& r) 
  166. {
  167. if (!valid ()) return; 
  168. if (where () == r) return; 
  169. CU8Image* puci = new CU8Image (*this, r);
  170. swap (*puci);
  171. delete puci;
  172. }
  173. CRct CU8Image::boundingBox (const PixelC pxlcOutsideColor) const
  174. {
  175. if (allValue ((PixelC) pxlcOutsideColor))
  176. return CRct ();
  177. CoordI left = where ().right - 1;
  178. CoordI top = where ().bottom - 1;
  179. CoordI right = where ().left;
  180. CoordI bottom = where ().top;
  181. const PixelC* ppxlcThis = pixels ();
  182. for (CoordI y = where ().top; y < where ().bottom; y++) {
  183. for (CoordI x = where ().left; x < where ().right; x++) {
  184. if (*ppxlcThis != (PixelC) pxlcOutsideColor) {
  185. left = min (left, x);
  186. top = min (top, y);
  187. right = max (right, x);
  188. bottom = max (bottom, y);
  189. }
  190. ppxlcThis++;
  191. }
  192. }
  193. right++;
  194. bottom++;
  195. return (CRct (left, top, right, bottom));
  196. }
  197. U8 CU8Image::mean () const
  198. {
  199. if (where ().empty ()) return 0;
  200. Int meanRet = 0;
  201. PixelC* ppxlc = (PixelC*) pixels ();
  202. UInt area = where ().area ();
  203. for (UInt ip = 0; ip < area; ip++)
  204. meanRet += ppxlc [ip];
  205. return (U8) (meanRet / area);
  206. }
  207. U8 CU8Image::mean (const CU8Image* puciMsk) const
  208. {
  209. assert (where () == puciMsk -> where ()); // no compute if rects are different
  210. if (where ().empty ()) return 0;
  211. Int meanRet = 0;
  212. PixelC* ppxlc = (PixelC*) pixels ();
  213. const PixelC* ppxlcMsk = puciMsk -> pixels ();
  214. UInt area = where ().area ();
  215. UInt uiNumNonTransp = 0;
  216. for (UInt ip = 0; ip < area; ip++) {
  217. if (ppxlcMsk [ip] != transpValue) {
  218. uiNumNonTransp++;
  219. meanRet += ppxlc [ip];
  220. }
  221. }
  222. return (U8) (meanRet / uiNumNonTransp);
  223. }
  224. Int CU8Image::sumDeviation (const CU8Image* puciMsk) const // sum of first-order deviation
  225. {
  226. U8 meanPxl = mean (puciMsk);
  227. Int devRet = 0;
  228. PixelC* ppxlc = (PixelC*) pixels ();
  229. const PixelC* ppxlcMsk = puciMsk -> pixels ();
  230. UInt area = where ().area ();
  231. for (UInt ip = 0; ip < area; ip++) {
  232. if (ppxlcMsk [ip] != transpValue)
  233. devRet += abs (meanPxl - ppxlc [ip]);
  234. }
  235. return devRet;
  236. }
  237. Int CU8Image::sumDeviation () const // sum of first-order deviation
  238. {
  239. U8 meanPxl = mean ();
  240. Int devRet = 0;
  241. PixelC* ppxlc = (PixelC*) pixels ();
  242. UInt area = where ().area ();
  243. for (UInt ip = 0; ip < area; ip++)
  244. devRet += abs (meanPxl - ppxlc [ip]);
  245. return devRet;
  246. }
  247. UInt CU8Image::sumAbs (const CRct& rct) const // sum of absolute value
  248. {
  249. CRct rctToDo = (!rct.valid ()) ? where () : rct;
  250. UInt uiRet = 0;
  251. if (rctToDo == where ()) {
  252. const PixelC* ppxlc = pixels ();
  253. UInt area = where ().area ();
  254. for (UInt ip = 0; ip < area; ip++, ppxlc++) {
  255. if (*ppxlc > 0) 
  256. uiRet += *ppxlc;
  257. else
  258. uiRet -= *ppxlc;
  259. }
  260. }
  261. else {
  262. Int width = where ().width;
  263. const PixelC* ppxlcRow = pixels (rct.left, rct.top);
  264. for (CoordI y = rctToDo.top; y < rctToDo.bottom; y++) {
  265. const PixelC* ppxlc = ppxlcRow;
  266. for (CoordI x = rctToDo.left; x < rctToDo.right; x++, ppxlc++) {
  267. if (*ppxlc > 0)
  268. uiRet += *ppxlc;
  269. else
  270. uiRet -= *ppxlc;
  271. }
  272. ppxlcRow += width;
  273. }
  274. }
  275. return uiRet;
  276. }
  277. Bool CU8Image::allValue (PixelC ucVl, const CRct& rct) const
  278. {
  279. CRct rctToDo = (!rct.valid ()) ? where () : rct;
  280. if (rctToDo == where ()) {
  281. const PixelC* ppxlc = pixels ();
  282. UInt area = where ().area ();
  283. for (UInt ip = 0; ip < area; ip++) {
  284. if (ppxlc [ip] != ucVl)
  285. return FALSE;
  286. }
  287. }
  288. else {
  289. Int width = where ().width;
  290. const PixelC* ppxlc = pixels (rct.left, rct.top);
  291. for (CoordI y = rctToDo.top; y < rctToDo.bottom; y++) {
  292. const PixelC* ppxlcRow = ppxlc;
  293. for (CoordI x = rctToDo.left; x < rctToDo.right; x++, ppxlcRow++) {
  294. if (*ppxlcRow != ucVl)
  295. return FALSE;
  296. }
  297. ppxlc += width;
  298. }
  299. }
  300. return TRUE;
  301. }
  302. Bool CU8Image::biLevel (const CRct& rct) const
  303. {
  304. CRct rctToDo = (!rct.valid ()) ? where () : rct;
  305. if (rctToDo == where ()) {
  306. const PixelC* ppxlc = pixels ();
  307. UInt area = where ().area ();
  308. for (UInt ip = 0; ip < area; ip++) {
  309. if (ppxlc [ip] != opaqueValue && ppxlc [ip] != transpValue )
  310. return FALSE;
  311. }
  312. }
  313. else {
  314. Int width = where ().width;
  315. const PixelC* ppxlc = pixels (rct.left, rct.top);
  316. for (CoordI y = rctToDo.top; y < rctToDo.bottom; y++) {
  317. const PixelC* ppxlcRow = ppxlc;
  318. for (CoordI x = rctToDo.left; x < rctToDo.right; x++, ppxlcRow++) {
  319. if (*ppxlcRow != opaqueValue && *ppxlcRow != transpValue )
  320. return FALSE;
  321. }
  322. ppxlc += width;
  323. }
  324. }
  325. return TRUE;
  326. }
  327. CRct CU8Image::whereVisible () const
  328. {
  329. CoordI left = where ().right - 1;
  330. CoordI top = where ().bottom - 1;
  331. CoordI right = where ().left;
  332. CoordI bottom = where ().top;
  333. const PixelC* ppxlcThis = pixels ();
  334. for (CoordI y = where ().top; y < where ().bottom; y++) {
  335. for (CoordI x = where ().left; x < where ().right; x++) {
  336. if (*ppxlcThis != transpValue) {
  337. left = min (left, x);
  338. top = min (top, y);
  339. right = max (right, x);
  340. bottom = max (bottom, y);
  341. }
  342. ppxlcThis++;
  343. }
  344. }
  345. right++;
  346. bottom++;
  347. return CRct (left, top, right, bottom);
  348. }
  349. Bool CU8Image::atLeastOneValue (PixelC ucVl, const CRct& rct) const
  350. {
  351. CRct rctRegionOfInterest = (!rct.valid ()) ? where () : rct;
  352. assert (rctRegionOfInterest <= where ());
  353. if (rctRegionOfInterest == where ()) {
  354. const PixelC* ppxlc = pixels ();
  355. UInt area = where ().area ();
  356. for (UInt ip = 0; ip < area; ip++) {
  357. if (ppxlc [ip] == ucVl)
  358. return TRUE;
  359. }
  360. }
  361. else {
  362. Int width = where ().width;
  363. const PixelC* ppxlc = pixels (rctRegionOfInterest.left, rctRegionOfInterest.top);
  364. for (CoordI y = rctRegionOfInterest.top; y < rctRegionOfInterest.bottom; y++) {
  365. const PixelC* ppxlcRow = ppxlc;
  366. for (CoordI x = rctRegionOfInterest.left; x < rctRegionOfInterest.right; x++, ppxlcRow++) {
  367. if (*ppxlcRow == ucVl)
  368. return TRUE;
  369. }
  370. ppxlc += width;
  371. }
  372. }
  373. return FALSE;
  374. }
  375. UInt CU8Image::numPixelsNotValued (PixelC ucVl, const CRct& rct) const // number of pixels not valued vl in region rct
  376. {
  377. CRct rctInterest = (!rct.valid ()) ? where () : rct;
  378. assert (rctInterest <= where ());
  379. UInt nRet = 0;
  380. if (rctInterest == where ()) {
  381. const PixelC* ppxlc = pixels ();
  382. UInt area = where ().area ();
  383. for (UInt ip = 0; ip < area; ip++) {
  384. if (ppxlc [ip] != ucVl)
  385. nRet++;
  386. }
  387. }
  388. else {
  389. Int width = where ().width;
  390. const PixelC* ppxlc = pixels (rctInterest.left, rctInterest.top);
  391. for (CoordI y = rctInterest.top; y < rctInterest.bottom; y++) {
  392. const PixelC* ppxlcRow = ppxlc;
  393. for (CoordI x = rctInterest.left; x < rctInterest.right; x++, ppxlcRow++) {
  394. if (*ppxlcRow != ucVl)
  395. nRet++;
  396. }
  397. ppxlc += width;
  398. }
  399. }
  400. return nRet;
  401. }
  402. Void CU8Image::setRect (const CRct& rct)
  403. {
  404. assert (rct.area () == m_rc.area ());
  405. m_rc = rct;
  406. }
  407. Void CU8Image::threshold (PixelC ucThresh)
  408. {
  409. PixelC* ppxlThis = (PixelC*) pixels ();
  410. UInt area = where ().area ();
  411. for (UInt id = 0; id < area; id++) {
  412. if (ppxlThis [id] < ucThresh)
  413. ppxlThis [id] = 0;
  414. }
  415. }
  416. Void CU8Image::binarize (PixelC ucThresh)
  417. {
  418. PixelC* ppxlcThis = (PixelC*) pixels ();
  419. UInt area = where ().area ();
  420. for (UInt id = 0; id < area; id++, ppxlcThis) {
  421. if (*ppxlcThis < ucThresh)
  422. *ppxlcThis = transpValue;
  423. else
  424. *ppxlcThis = opaqueValue;
  425. }
  426. }
  427. /* NBIT: change U8 to PixelC
  428. Void CU8Image::checkRange (U8 ucMin, U8 ucMax)
  429. */
  430. Void CU8Image::checkRange (PixelC ucMin, PixelC ucMax)
  431. {
  432. PixelC* ppxlcThis = (PixelC*) pixels ();
  433. UInt area = where ().area ();
  434. for (UInt id = 0; id < area; id++, ppxlcThis++)
  435. *ppxlcThis = checkrange (*ppxlcThis, ucMin, ucMax);
  436. }
  437. own CU8Image* CU8Image::decimate (UInt rateX, UInt rateY) const
  438. {
  439. const CoordI left = where ().left / (CoordI) rateX;
  440. const CoordI top = where ().top / (CoordI)  rateY;
  441. const CoordI right = 
  442. (where ().right >= 0) ? (where ().right + (CoordI) rateX - 1) / (CoordI) rateX :
  443. (where ().right - (CoordI) rateX + 1) / (CoordI) rateX;
  444. const CoordI bottom = 
  445. (where ().bottom >= 0) ? (where ().bottom + (CoordI) rateX - 1) / (CoordI) rateY :
  446. (where ().bottom - (CoordI) rateX + 1) / (CoordI) rateY;
  447. CU8Image* puciRet = new CU8Image (CRct (left, top, right, bottom));
  448. PixelC* ppxlcRet = (PixelC*) puciRet -> pixels ();
  449. const PixelC* ppxlcOrgY = pixels ();
  450. Int skipY = rateY * where ().width;
  451. for (CoordI y = top; y < bottom; y++) {
  452. const PixelC* ppxlcOrgX = ppxlcOrgY;
  453. for (CoordI x = left; x < right; x++) {
  454. *ppxlcRet++ = *ppxlcOrgX;
  455. ppxlcOrgX += rateX;
  456. }
  457. ppxlcOrgY += skipY;
  458. }
  459. return puciRet;
  460. }
  461. own CU8Image* CU8Image::decimateBinaryShape (UInt rateX, UInt rateY) const
  462. {
  463. const CoordI left = where ().left / (CoordI) rateX;
  464. const CoordI top = where ().top / (CoordI) rateY;
  465. Int roundR = (where ().right >= 0) ? rateX - 1 : 1 - rateX;
  466. Int roundB = (where ().bottom >= 0) ? rateY - 1 : 1 - rateY;
  467. const CoordI right = (where ().right + roundR) / (CoordI) rateX;
  468. const CoordI bottom = (where ().bottom + roundB) / (CoordI) rateY;
  469. CU8Image* puciRet = new CU8Image (CRct (left, top, right, bottom));
  470. PixelC* ppxlcRet = (PixelC*) puciRet -> pixels ();
  471. const PixelC* ppxlcOrgY = pixels ();
  472. Int skipY = rateY * where ().width;
  473. CoordI x, y;
  474. CoordI iXOrigLeft, iYOrigTop; //left top of a sampling square
  475. for (y = top, iYOrigTop = where().top; y < bottom; y++, iYOrigTop += rateY) {
  476. const PixelC* ppxlcOrgX = ppxlcOrgY;
  477. for (x = left, iXOrigLeft = where().left; x < right; x++, iXOrigLeft += rateX) {
  478. CoordI iXOrig, iYOrig; //for scanning of the sampling square
  479. const PixelC* ppxlcOrigScanY = ppxlcOrgX; //same
  480. *ppxlcRet = transpValue;
  481. for (iYOrig = iYOrigTop; iYOrig < (iYOrigTop + (Int) rateY); iYOrig++) {
  482. if (iYOrig >= where().bottom || *ppxlcRet == opaqueValue)
  483. break;
  484. const PixelC* ppxlcOrigScanX = ppxlcOrigScanY; //for scan also
  485. //Bool bStopScan = FALSE;
  486. for (iXOrig = iXOrigLeft; iXOrig < (iXOrigLeft + (Int) rateX); iXOrig++) {
  487. if (iXOrig >= where().right)
  488. break;
  489. assert (*ppxlcOrigScanX == transpValue || *ppxlcOrigScanX == opaqueValue);
  490. if (*ppxlcOrigScanX == opaqueValue) {
  491. *ppxlcRet = opaqueValue;
  492. break;
  493. }
  494. ppxlcOrigScanX++;
  495. }
  496. ppxlcOrigScanY += where().width;
  497. }
  498. assert (*ppxlcRet == transpValue || *ppxlcRet == opaqueValue);
  499. ppxlcRet++;
  500. ppxlcOrgX += rateX;
  501. }
  502. ppxlcOrgY += skipY;
  503. }
  504. return puciRet;
  505. }
  506. own CU8Image* CU8Image::zoomup (UInt rateX, UInt rateY) const
  507. {
  508. const CoordI left = where ().left * rateX; // left-top coordinate remain the same
  509. const CoordI top = where ().top * rateY;
  510. const CoordI right = where ().right * rateX;
  511. const CoordI bottom = where ().bottom * rateY;
  512. CU8Image* puciRet = new CU8Image (CRct (left, top, right, bottom));
  513. PixelC* ppxlRet = (PixelC*) puciRet -> pixels ();
  514. for (CoordI y = top; y < bottom; y++) {
  515. for (CoordI x = left; x < right; x++)
  516. *ppxlRet++ = pixel ((CoordI) (x / (CoordI) rateX), (CoordI) (y / (CoordI) rateY));
  517. }
  518. return puciRet;
  519. }
  520. own CU8Image* CU8Image::expand (UInt rateX, UInt rateY) const // expand by putting zeros in between
  521. {
  522. const CoordI left = where ().left * rateX; // left-top coordinate remain the same
  523. const CoordI top = where ().top * rateY;
  524. const CoordI right = where ().right * rateX;
  525. const CoordI bottom = where ().bottom * rateY;
  526. CU8Image* puciRet = new CU8Image (CRct (left, top, right, bottom));
  527. PixelC* ppxlRet = (PixelC*) puciRet -> pixels ();
  528. const PixelC* ppxlThis = pixels ();
  529. for (CoordI y = top; y < bottom; y++) {
  530. for (CoordI x = left; x < right; x++) {
  531. if (x % rateX == 0 && y % rateY == 0) 
  532. *ppxlRet++ = *ppxlThis++;
  533. else
  534. *ppxlRet++ = 0;
  535. }
  536. }
  537. return puciRet;
  538. }
  539. own CU8Image* CU8Image::biInterpolate () const // bilinearly interpolate the vframe
  540. {
  541. const CoordI left = where ().left << 1; // left-top coordinate remain the same
  542. const CoordI top = where ().top << 1;
  543. const CoordI right = where ().right << 1;
  544. const CoordI bottom = where ().bottom << 1;
  545. const CoordI width = right - left;
  546. CoordI x, y;
  547. CU8Image* puciRet = new CU8Image (CRct (left, top, right, bottom));
  548. PixelC* ppxlcRet = (PixelC*) puciRet -> pixels ();
  549. const PixelC* ppxlc = pixels ();
  550. const CoordI right1 = right - 2;
  551. for (y = top; y < bottom; y += 2) { // x-direction interpolation
  552. for (x = left; x < right1; x += 2) {
  553. *ppxlcRet++ = *ppxlc++;
  554. *ppxlcRet++ = (*ppxlc + *(ppxlc - 1) + 1) >> 1;
  555. }
  556. *ppxlcRet++ = *ppxlc;
  557. *ppxlcRet++ = *ppxlc++; // the last pixel of every row do not need average
  558. ppxlcRet += width;
  559. }
  560. ppxlcRet = (PixelC*) puciRet -> pixels ();
  561. ppxlcRet += width; // start from the second row
  562. const CoordI width2 = width << 1;
  563. const CoordI bottom1 = bottom - 1;
  564. for (x = left; x < right; x++) { // y-direction interpolation
  565. PixelC* ppxlcRett = ppxlcRet++;
  566. for (y = top + 1; y < bottom1; y += 2) {
  567. *ppxlcRett = (*(ppxlcRett - width) + *(ppxlcRett + width) + 1) >> 1;
  568. ppxlcRett += width2;
  569. }
  570. *ppxlcRett = *(ppxlcRett - width); // the last pixel of every column do not need average
  571. }
  572. return puciRet;
  573. }
  574. own CU8Image* CU8Image::downsampleForSpatialScalability () const
  575. {
  576. static Int rgiFilterVertical[13] = {2, 0, -4, -3, 5, 19, 26, 19, 5, -3, -4, 0, 2};
  577. static Int rgiFilterHorizontal[4] = {5, 11, 11, 5};
  578. Int iWidthSrc = where (). width;
  579. Int iHeightSrc = where (). height ();
  580. assert (iWidthSrc % 2 == 0 && iHeightSrc % 2 == 0);
  581. Int iWidthDst = iWidthSrc / 2;
  582. Int iHeightDst = iHeightSrc / 2;
  583. CU8Image* puciBuffer = new CU8Image (CRct (0, 0, iWidthSrc, iHeightDst));
  584. CU8Image* puciRet = new CU8Image (CRct (0, 0, iWidthDst, iHeightDst));
  585. assert (puciBuffer != NULL);
  586. assert (puciRet != NULL);
  587. //filter and downsample vertically
  588. const PixelC* ppxlcSrc;
  589. const PixelC* ppxlcColumnHeadSrc = pixels ();
  590. PixelC* ppxlcDst = (PixelC*) puciBuffer->pixels ();
  591. PixelC* ppxlcColumnHeadDst = (PixelC*) puciBuffer->pixels ();
  592. Int i, j, k;
  593. for (i = 0; i < iWidthSrc; i++) {
  594. ppxlcSrc = ppxlcColumnHeadSrc;
  595. ppxlcDst = ppxlcColumnHeadDst;
  596. for (j = 0; j < iHeightDst; j++) {
  597. k = j * 2;         
  598. const PixelC* ppxlcMinusOne = ( k < 1 ) ? ppxlcSrc : ppxlcSrc - iWidthSrc;
  599. const PixelC* ppxlcMinusTwo = ( k < 2 ) ? ppxlcSrc : ppxlcMinusOne - iWidthSrc;
  600. const PixelC* ppxlcMinusThree = ( k < 3 ) ? ppxlcSrc : ppxlcMinusTwo - iWidthSrc;
  601. const PixelC* ppxlcMinusFour = ( k < 4 ) ? ppxlcSrc : ppxlcMinusThree - iWidthSrc;
  602. const PixelC* ppxlcMinusFive = ( k < 5 ) ? ppxlcSrc : ppxlcMinusFour - iWidthSrc;
  603. const PixelC* ppxlcMinusSix = ( k < 6 ) ? ppxlcSrc : ppxlcMinusFive - iWidthSrc;
  604. const PixelC* ppxlcPlusOne = ( k >= iHeightSrc - 1) ? ppxlcSrc : ppxlcSrc + iWidthSrc;
  605. const PixelC* ppxlcPlusTwo = ( k >= iHeightSrc - 2) ? ppxlcPlusOne : ppxlcPlusOne + iWidthSrc;
  606. const PixelC* ppxlcPlusThree = ( k >= iHeightSrc - 3) ? ppxlcPlusTwo : ppxlcPlusTwo + iWidthSrc;
  607. const PixelC* ppxlcPlusFour = ( k >= iHeightSrc - 4) ? ppxlcPlusThree : ppxlcPlusThree + iWidthSrc;
  608. const PixelC* ppxlcPlusFive = ( k >= iHeightSrc - 5) ? ppxlcPlusFour : ppxlcPlusFour + iWidthSrc;
  609. const PixelC* ppxlcPlusSix = ( k >= iHeightSrc - 6) ? ppxlcPlusFive : ppxlcPlusFive + iWidthSrc;
  610. *ppxlcDst = checkrangeU8 (
  611. (U8) ((*ppxlcMinusSix * rgiFilterVertical [0] +
  612. *ppxlcMinusFive * rgiFilterVertical [1] +
  613. *ppxlcMinusFour * rgiFilterVertical [2] +
  614. *ppxlcMinusThree * rgiFilterVertical [3] +
  615. *ppxlcMinusTwo * rgiFilterVertical [4] +
  616. *ppxlcMinusOne * rgiFilterVertical [5] +
  617. *ppxlcSrc * rgiFilterVertical [6] +
  618. *ppxlcPlusOne * rgiFilterVertical [7] +
  619. *ppxlcPlusTwo * rgiFilterVertical [8] +
  620. *ppxlcPlusThree * rgiFilterVertical [9] +
  621. *ppxlcPlusFour * rgiFilterVertical [10] +
  622. *ppxlcPlusFive * rgiFilterVertical [11] +
  623. *ppxlcPlusSix * rgiFilterVertical [12] + 32) >> 6),
  624. 0, 255
  625. );
  626. ppxlcSrc += 2 * iWidthSrc;
  627. ppxlcDst += iWidthSrc;
  628. }
  629. ppxlcColumnHeadSrc++;
  630. ppxlcColumnHeadDst++;
  631. //filter and downsample horizontally
  632. ppxlcSrc = puciBuffer->pixels ();
  633. ppxlcDst = (PixelC*) puciRet->pixels ();
  634. for (j = 0; j < iHeightDst; j++) {
  635. for (i = 0; i < iWidthDst; i++) {
  636. k = i * 2;         
  637. const PixelC* ppxlcMinusOne = ( k < 1 ) ? ppxlcSrc : ppxlcSrc - 1;
  638. const PixelC* ppxlcPlusOne = ( k >= iWidthSrc - 1) ? ppxlcSrc : ppxlcSrc + 1;
  639. const PixelC* ppxlcPlusTwo = ( k >= iWidthSrc - 2) ? ppxlcSrc : ppxlcSrc + 2;
  640. *ppxlcDst = checkrangeU8 (
  641. (U8) ((*ppxlcMinusOne * rgiFilterHorizontal [0] +
  642. *ppxlcSrc * rgiFilterHorizontal [1] +
  643. *ppxlcPlusOne * rgiFilterHorizontal [2] +
  644. *ppxlcPlusTwo * rgiFilterHorizontal [3] + 16) >> 5),
  645. 0, 255
  646. );
  647. ppxlcSrc += 2;
  648. ppxlcDst++;
  649. }
  650. delete puciBuffer;
  651. return puciRet;
  652. }
  653. own CU8Image* CU8Image::upsampleForSpatialScalability ( Int iVerticalSamplingFactorM,
  654. Int iVerticalSamplingFactorN,
  655. Int iHorizontalSamplingFactorM,
  656. Int iHorizontalSamplingFactorN,
  657. Int iType,
  658. Int iExpandYRefFrame
  659. ) const
  660. {
  661. /* SONY
  662. CRct rctDst = where () * 2;
  663. rctDst.right -=iExpandYRefFrame/iType;
  664. rctDst.bottom-=iExpandYRefFrame/iType;
  665. rctDst.left  +=iExpandYRefFrame/iType;
  666. rctDst.top   +=iExpandYRefFrame/iType;
  667. rctDst.width -=iExpandYRefFrame/iType*2;
  668. CRct rctBuf2 = where()*2;
  669. Int iWidthSrc = where (). width ;
  670. Int iHeightSrc = where (). height ();
  671. Int iWidthDst = iWidthSrc*2;
  672. Int iHeightDst = iHeightSrc*2;
  673. */
  674. CRct rctDst = where ();
  675. Float tmp;
  676. rctDst.right -= iExpandYRefFrame/iType;
  677. tmp = (Float)  rctDst.right * ((Float)iHorizontalSamplingFactorN/iHorizontalSamplingFactorM);
  678. rctDst.right = (Int) tmp;
  679. rctDst.right += iExpandYRefFrame/iType;
  680. rctDst.left += iExpandYRefFrame/iType;
  681. tmp = (Float)rctDst.left*((Float)iHorizontalSamplingFactorN/iHorizontalSamplingFactorM);
  682. rctDst.left  = (Int) tmp;
  683. rctDst.left -= iExpandYRefFrame/iType;
  684. rctDst.width -= iExpandYRefFrame/iType*2;
  685. tmp = (Float) rctDst.width * ((Float)iHorizontalSamplingFactorN/iHorizontalSamplingFactorM);
  686. rctDst.width = (Int ) tmp;
  687. rctDst.width += iExpandYRefFrame/iType*2;
  688. rctDst.bottom -= iExpandYRefFrame/iType;
  689. tmp = (Float) rctDst.bottom * ((Float)iVerticalSamplingFactorN/iVerticalSamplingFactorM);
  690. rctDst.bottom = (Int) tmp;
  691. rctDst.bottom += iExpandYRefFrame/iType;
  692. rctDst.top += iExpandYRefFrame/iType;
  693. tmp = (Float) rctDst.top * ((Float)iVerticalSamplingFactorN/iVerticalSamplingFactorM);
  694. rctDst.top = (Int) tmp;
  695. rctDst.top -= iExpandYRefFrame/iType;
  696. Int iWidthSrc = where (). width ;
  697. Int iHeightSrc = where (). height ();
  698. tmp = (Float) iWidthSrc*((Float)iHorizontalSamplingFactorN/iHorizontalSamplingFactorM);
  699. //Int iWidthDst = (Int) tmp;
  700. tmp = (Float)  iHeightSrc*((Float)iVerticalSamplingFactorN/iVerticalSamplingFactorM);
  701. //Int iHeightDst = (Int) tmp;
  702. //wchen: this approach is very slow; will have to change later
  703. /* CU8Image* puciBuffer = new CU8Image (CRct (where().left, rctBuf2.top, where().right, rctBuf2.bottom));
  704. CU8Image* puciBuffer2 = new CU8Image (CRct (rctBuf2.left,rctBuf2.top, rctBuf2.right,rctBuf2.bottom));*/
  705. CU8Image* puciRet = new CU8Image (CRct (rctDst.left, rctDst.top, rctDst.right, rctDst.bottom));
  706. //upsample vertically
  707. PixelC* ppxlcDst;
  708. const PixelC* ppxlcColumnHeadSrc = pixels ();
  709. /*
  710. Int iVerticalSamplingFactorM = m_volmd.iver_sampling_factor_m;
  711. Int iVerticalSamplingFactorN = m_volmd.iver_sampling_factor_n;
  712. Int iHorizontalSamplingFactorM = m_volmd.ihor_sampling_factor_m;
  713. Int iHorizontalSamplingFactorN = m_volmd.ihor_sampling_factor_n;
  714. */
  715. Int x,y,y1,y2,x1,x2;
  716. Int phase = 0;
  717.   
  718. Int *pict_vert;
  719. const PixelC* pict= ppxlcColumnHeadSrc +iWidthSrc*iExpandYRefFrame/iType+iExpandYRefFrame/iType;
  720. ppxlcDst = (PixelC *)puciRet->pixels();
  721. //wchen: should not malloc at every call; need to change later
  722. //pict_vert = (Int *) malloc (sizeof(Int)*((where().width-iExpandYRefFrame/iType*2)*(where().height()-iExpandYRefFrame/iType*2)*2));
  723. // bug fix from Takefumi Nagumo 6/21/99
  724. pict_vert = (Int *) malloc (sizeof(Int) * (Int)(1 + (where().width-iExpandYRefFrame/iType*2)
  725. * (where().height()-iExpandYRefFrame/iType*2) * ((Float)iVerticalSamplingFactorN / (Float)iVerticalSamplingFactorM) ) );
  726. for(x=0;x< (where().width-iExpandYRefFrame/iType*2); x++)
  727. for(y=0;y< (rctDst.height()-iExpandYRefFrame/iType*2); y++) {
  728. y1 = (y*iVerticalSamplingFactorM )/iVerticalSamplingFactorN;
  729. if(y1 < where().height() - iExpandYRefFrame/iType*2 - 1)
  730. y2 = y1+1;
  731. else
  732. y2 = y1;
  733. phase = (16*((y*iVerticalSamplingFactorM) %
  734. iVerticalSamplingFactorN) + iVerticalSamplingFactorN/2 /*for rounding*/)
  735. /iVerticalSamplingFactorN;
  736. *(pict_vert+y*(where().width-iExpandYRefFrame/iType*2)+x) = (Int)(16-phase)*(*(pict+y1*where().width+x))
  737. + phase *(*(pict+y2*where().width+x));
  738. }
  739.   
  740. for(y=0;y< rctDst.height()-iExpandYRefFrame*2/iType; y++)
  741. for(x=0;x< rctDst.width -iExpandYRefFrame*2/iType; x++) {
  742. x1 = (x*iHorizontalSamplingFactorM )/iHorizontalSamplingFactorN;
  743. if(x1 < where().width  - iExpandYRefFrame/iType*2 - 1)
  744. x2 = x1+1;
  745. else
  746. x2 = x1;
  747. // Warning:no rounding
  748. phase = (16*((x*iHorizontalSamplingFactorM) %
  749. iHorizontalSamplingFactorN) + iHorizontalSamplingFactorN/2 /*for rounding*/)
  750. / iHorizontalSamplingFactorN;
  751. *(ppxlcDst+(x+iExpandYRefFrame/iType)+(y+iExpandYRefFrame/iType)*rctDst.width)
  752.   =(PixelC)(((16-phase)*(*(pict_vert+y*(where().width-iExpandYRefFrame/iType*2)+x1))
  753. + phase *(*(pict_vert+y*(where().width-iExpandYRefFrame/iType*2)+x2)) +128 )>>8 );
  754. }
  755. free(pict_vert);  
  756. /* delete puciBuffer;
  757. delete puciBuffer2;*/
  758. return puciRet;
  759. }
  760. own CU8Image* CU8Image::biInterpolate (UInt accuracy) const // bilinearly interpolate the vframe
  761. {
  762. const CoordI left = where ().left * accuracy;
  763. const CoordI top = where ().top * accuracy;
  764. const CoordI right = where ().right * accuracy;
  765. const CoordI bottom = where ().bottom * accuracy;
  766. CU8Image* puciRet = new CU8Image (CRct (left, top, right, bottom));
  767. PixelC* ppxlcRet = (PixelC*) puciRet -> pixels ();
  768. for (CoordI y = top; y < bottom; y++) { // x-direction interpolation
  769. for (CoordI x = left; x < right; x++) {
  770. *ppxlcRet = pixel (x, y, accuracy);
  771. ppxlcRet++;
  772. }
  773. }
  774. return puciRet;
  775. }
  776. own CU8Image* CU8Image::transpose () const
  777. {
  778. CRct rctDst = where ();
  779. rctDst.transpose ();
  780. CU8Image* puciDst = new CU8Image (rctDst);
  781. const PixelC* ppxlSrc = pixels ();
  782. PixelC* ppxlDstRow = (PixelC*) puciDst->pixels ();
  783. PixelC* ppxlDst;
  784. UInt height = where ().height ();
  785. for (CoordI iy = where ().top; iy < where ().bottom; iy++) {
  786. ppxlDst = ppxlDstRow;
  787. for (CoordI ix = where ().left; ix < where ().right; ix++) {
  788. *ppxlDst = *ppxlSrc++;
  789. ppxlDst += height;
  790. }
  791. ppxlDstRow++;
  792. }
  793. return puciDst;
  794. }
  795. own CU8Image* CU8Image::warp (const CAffine2D& aff) const // affine warp
  796. {
  797. CSiteD stdLeftTopWarp = aff * CSiteD (where ().left, where ().top);
  798. CSiteD stdRightTopWarp = aff * CSiteD (where ().right, where ().top);
  799. CSiteD stdLeftBottomWarp = aff * CSiteD (where ().left, where ().bottom);
  800. CSiteD stdRightBottomWarp = aff * CSiteD (where ().right, where ().bottom);
  801. CRct rctWarp (stdLeftTopWarp, stdRightTopWarp, stdLeftBottomWarp, stdRightBottomWarp);
  802. CU8Image* puciRet = new CU8Image (rctWarp);
  803. PixelC* ppxlcRet = (PixelC*) puciRet -> pixels ();
  804. CAffine2D affInv = aff.inverse ();
  805. for (CoordI y = rctWarp.top; y < rctWarp.bottom; y++) {
  806. for (CoordI x = rctWarp.left; x < rctWarp.right; x++) {
  807. CSiteD src = affInv * CSiteD (x, y); 
  808. CoordI fx = (CoordI) floor (src.x); //.5 is for better truncation
  809. CoordI fy = (CoordI) floor (src.y); //.5 is for better truncation
  810. CoordI cx = (CoordI) ceil (src.x); //.5 is for better truncation
  811. CoordI cy = (CoordI) ceil (src.y); //.5 is for better truncation
  812. if (
  813. where ().includes (fx, fy) && 
  814. where ().includes (fx, cy) && 
  815. where ().includes (cx, fy) && 
  816. where ().includes (cx, cy)
  817. )
  818. *ppxlcRet = pixel (src);
  819. ppxlcRet++;
  820. }
  821. }
  822. return puciRet;
  823. }
  824. own CU8Image* CU8Image::warp (const CPerspective2D& persp) const // perspective warp
  825. {
  826. CSiteD src [4], dest [4];
  827. src [0] = CSiteD (where ().left, where ().top);
  828. src [1] = CSiteD (where ().right, where ().top);
  829. src [2] = CSiteD (where ().left, where ().bottom);
  830. src [3] = CSiteD (where ().right, where ().bottom);
  831. for (UInt i = 0; i < 4; i++) {
  832. dest [i] = (persp * src [i]).s;
  833. }
  834. CRct rctWarp (dest [0], dest [1], dest [2], dest [3]);
  835. CU8Image* puciRet = new CU8Image (rctWarp);
  836. PixelC* ppxlcRet = (PixelC*) puciRet -> pixels ();
  837. CPerspective2D perspInv = CPerspective2D (dest, src);
  838. for (CoordI y = rctWarp.top; y != rctWarp.bottom; y++) {
  839. for (CoordI x = rctWarp.left; x != rctWarp.right; x++) {
  840. CSiteD src = (perspInv * CSiteD (x, y)).s; 
  841. CoordI fx = (CoordI) floor (src.x); //.5 is for better truncation
  842. CoordI fy = (CoordI) floor (src.y); //.5 is for better truncation
  843. CoordI cx = (CoordI) ceil (src.x); //.5 is for better truncation
  844. CoordI cy = (CoordI) ceil (src.y); //.5 is for better truncation
  845. if (
  846. where ().includes (fx, fy) && 
  847. where ().includes (fx, cy) && 
  848. where ().includes (cx, fy) && 
  849. where ().includes (cx, cy)
  850. )
  851. *ppxlcRet = pixel (src);
  852. ppxlcRet++;
  853. }
  854. }
  855. return puciRet;
  856. }
  857. own CU8Image* CU8Image::warp (const CPerspective2D& persp, const CRct& rctWarp) const // perspective warp
  858. {
  859. CU8Image* puciRet = new CU8Image (rctWarp);
  860. PixelC* ppxlcRet = (PixelC*) puciRet -> pixels ();
  861. CPerspective2D perspInv = persp.inverse ();
  862. for (CoordI y = rctWarp.top; y != rctWarp.bottom; y++) {
  863. for (CoordI x = rctWarp.left; x != rctWarp.right; x++) {
  864. CSiteD src = (perspInv * CSiteD (x, y)).s; 
  865. CoordI fx = (CoordI) floor (src.x); //.5 is for better truncation
  866. CoordI fy = (CoordI) floor (src.y); //.5 is for better truncation
  867. CoordI cx = (CoordI) ceil (src.x); //.5 is for better truncation
  868. CoordI cy = (CoordI) ceil (src.y); //.5 is for better truncation
  869. if (
  870. where ().includes (fx, fy) && 
  871. where ().includes (fx, cy) && 
  872. where ().includes (cx, fy) && 
  873. where ().includes (cx, cy)
  874. )
  875. *ppxlcRet = pixel (src);
  876. ppxlcRet++;
  877. }
  878. }
  879. return puciRet;
  880. }
  881. own CU8Image* CU8Image::warp (const CPerspective2D& persp, const CRct& rctWarp, const UInt accuracy) const // perspective warp
  882. {
  883. CU8Image* puciRet = new CU8Image (rctWarp);
  884. PixelC* ppxlcRet = (PixelC*) puciRet -> pixels ();
  885. for (CoordI y = rctWarp.top; y != rctWarp.bottom; y++) {
  886. for (CoordI x = rctWarp.left; x != rctWarp.right; x++) {
  887. CSite src = (persp * CSite (x, y)).s; 
  888. CoordI fx = (CoordI) floor ((CoordD) src.x / (CoordD) accuracy); //.5 is for better truncation
  889. CoordI fy = (CoordI) floor ((CoordD) src.y / (CoordD) accuracy); //.5 is for better truncation
  890. CoordI cx = (CoordI) ceil ((CoordD) src.x / (CoordD) accuracy); //.5 is for better truncation
  891. CoordI cy = (CoordI) ceil ((CoordD) src.y / (CoordD) accuracy); //.5 is for better truncation
  892. if (
  893. where ().includes (fx, fy) && 
  894. where ().includes (fx, cy) && 
  895. where ().includes (cx, fy) && 
  896. where ().includes (cx, cy)
  897. )
  898. *ppxlcRet = pixel (src, accuracy);
  899. ppxlcRet++;
  900. }
  901. }
  902. return puciRet;
  903. }
  904. PixelC CU8Image::pixel (CoordD x, CoordD y) const
  905. {
  906. CoordI left = (CoordI) floor (x); // find the coordinates of the four corners
  907. CoordI wLeft = where ().left, wRight1 = where ().right - 1, wTop = where ().top, wBottom1 = where ().bottom - 1;
  908. left = checkrange (left, wLeft, wRight1);
  909. CoordI right = (CoordI) ceil (x);
  910. right = checkrange (right, wLeft, wRight1);
  911. CoordI top = (CoordI) floor (y);
  912. top = checkrange (top, wTop, wBottom1);
  913. CoordI bottom = (CoordI) ceil (y);
  914. bottom = checkrange (bottom, wTop, wBottom1);
  915. const PixelC lt = pixel (left, top);
  916. const PixelC rt = pixel (right, top);
  917. const PixelC lb = pixel (left, bottom);
  918. const PixelC rb = pixel (right, bottom);
  919. const Double distX = x - left;
  920. const Double distY = y - top;
  921. Double x01 = distX * (rt - lt) + lt; // use p.59's notation (Wolberg, Digital Image Warping)
  922. Double x23 = distX * (rb - lb) + lb;
  923. PixelC pxlRet = checkrangeU8 ((U8) (x01 + (x23 - x01) * distY + .5), 0, 255);
  924. return pxlRet;
  925. }
  926. PixelC CU8Image::pixel (CoordI x, CoordI y, UInt accuracy) const
  927. {
  928. UInt uis = 1 << (accuracy + 1);
  929. UInt accuracy1 = accuracy + 1;
  930. CoordD dx = (CoordD) ((CoordD) x / uis);
  931. CoordD dy = (CoordD) ((CoordD) y / uis);
  932. CoordI left = (CoordI) floor (dx); // find the coordinates of the four corners
  933. CoordI wLeft = where ().left, wRight1 = where ().right - 1, wTop = where ().top, wBottom1 = where ().bottom - 1;
  934. left = checkrange (left, wLeft, wRight1);
  935. CoordI right = (CoordI) ceil (dx);
  936. right = checkrange (right, wLeft, wRight1);
  937. CoordI top = (CoordI) floor (dy);
  938. top = checkrange (top, wTop, wBottom1);
  939. CoordI bottom = (CoordI) ceil (dy);
  940. bottom = checkrange (bottom, wTop, wBottom1);
  941. UInt accuracy2 = (accuracy << 1) + 2;
  942. const PixelC lt = pixel (left, top);
  943. const PixelC rt = pixel (right, top);
  944. const PixelC lb = pixel (left, bottom);
  945. const PixelC rb = pixel (right, bottom);
  946. const CoordI distX = x - (left << accuracy1);
  947. const CoordI distY = y - (top << accuracy1);
  948. Int dRet = ((uis-distY)*((uis-distX)*lt + distX*rt) + distY*((uis-distX)*lb + distX*rb) + (1<<(accuracy2-1))) >> accuracy2;
  949. PixelC pxlRet = (U8) checkrange ((PixelC)dRet, 0U, 255U);
  950. return pxlRet;
  951. }
  952. own CU8Image* CU8Image::complement () const
  953. {
  954. CU8Image* puciDst = new CU8Image (where(), (PixelC) transpValue);
  955. const PixelC* ppxlcSrc = pixels ();
  956. PixelC* ppxlcDst = (PixelC*) puciDst->pixels ();
  957. for (UInt iPxl = 0; iPxl < where ().area (); iPxl++)
  958. *ppxlcDst++ = *ppxlcSrc++ ^ 0xFF;
  959. return puciDst;
  960. }
  961. Void CU8Image::overlay (const CU8Image& uci)
  962. {
  963. if (!valid () || !uci.valid () || uci.where ().empty ()) return;
  964. CRct r = m_rc; 
  965. r.include (uci.m_rc); // overlay is defined on union of rects
  966. where (r); 
  967. if (!valid ()) return; 
  968. assert (uci.m_ppxlc != NULL); 
  969. CRct rctFi = uci.m_rc;
  970. Int widthFi = rctFi.width;
  971. Int widthCurr = where ().width;
  972. PixelC* ppxlcThis = (PixelC*) pixels (rctFi.left, rctFi.top);
  973. const PixelC* ppxlcFi = uci.pixels ();
  974. for (CoordI y = rctFi.top; y < rctFi.bottom; y++) { // loop through VOP CRct
  975. memcpy (ppxlcThis, ppxlcFi, rctFi.width * sizeof (PixelC));
  976. ppxlcThis += widthCurr; 
  977. ppxlcFi += widthFi;
  978. }
  979. }
  980. Void CU8Image::overlay (const CU8Image& uci, const CRct& rctSrc)
  981. {
  982. if (!valid () || !uci.valid () || uci.where ().empty () || !rctSrc.valid ()) return;
  983. if (!(uci.m_rc >= rctSrc))
  984. return;
  985. CRct r = m_rc; 
  986. r.include (rctSrc); // overlay is defined on union of rects
  987. where (r); 
  988. if (!valid ()) return; 
  989. assert (uci.m_ppxlc != NULL); 
  990. Int widthSrc = rctSrc.width;
  991. Int widthDst = where ().width;
  992. PixelC* ppxlcThis = (PixelC*) pixels (rctSrc.left, rctSrc.top);
  993. const PixelC* ppxlcSrc = uci.pixels (rctSrc.left, rctSrc.top);
  994. for (CoordI y = rctSrc.top; y < rctSrc.bottom; y++) { // loop through VOP CRct
  995. memcpy (ppxlcThis, ppxlcSrc, widthSrc * sizeof (PixelC));
  996. ppxlcThis += widthDst; 
  997. ppxlcSrc += widthSrc;
  998. }
  999. }
  1000. own CU8Image* CU8Image::smooth_ (UInt window) const
  1001. {
  1002. const UInt offset = window >> 1;
  1003. const UInt offset2 = offset << 1;
  1004. const UInt size = window * window; // array size to be sorted
  1005. const UInt med = size >> 1;
  1006. CU8Image* pfmgRet = new CU8Image (*this);
  1007. // bound of the image to be filtered.
  1008. const CoordI left = where ().left + offset;
  1009. const CoordI top = where ().top + offset;
  1010. const CoordI right = where ().right - offset;
  1011. const CoordI bottom = where ().bottom - offset;
  1012. const Int width = where ().width;
  1013. const Int dist = offset + offset * width;
  1014. const Int wwidth = width - window;
  1015. PixelC* rgValues = new PixelC [size];
  1016. PixelC* pRet = (PixelC*) pfmgRet -> pixels (left, top);
  1017. const PixelC* p = pixels (left, top);
  1018. for (CoordI y = top; y != bottom; y++) {
  1019. for (CoordI x = left; x != right; x++) {
  1020. const PixelC* pp = p - dist; // get correct index
  1021. UInt numTransp = 0;
  1022. for (UInt sy = 0; sy < window; sy++) {
  1023. for (UInt sx = 0; sx < window; sx++) {
  1024. if (*pp == transpValue)
  1025. numTransp++;
  1026. pp++;
  1027. }
  1028. pp += wwidth;
  1029. }
  1030. *pRet++ = (PixelC) ((numTransp <= med) ? opaqueValue : transpValue);
  1031. p++;
  1032. }
  1033. pRet += offset2;
  1034. p += offset2;
  1035. }
  1036. delete [] rgValues;
  1037. return pfmgRet;
  1038. }
  1039. own CU8Image* CU8Image::smooth (UInt window) const
  1040. {
  1041. UInt offset = window >> 1;
  1042. CRct rctExp (where ());
  1043. rctExp.expand (offset);
  1044. CU8Image* puciExp = new CU8Image (*this, rctExp);
  1045. CU8Image* puciSmooth = puciExp -> smooth_ (window);
  1046. puciSmooth -> where (where ());
  1047. delete puciExp;
  1048. return puciSmooth;
  1049. }
  1050. Void CU8Image::CU8Image_xor (const CU8Image& uci)
  1051. {
  1052. CRct rctIntersect = m_rc;
  1053. rctIntersect.clip (uci.where());
  1054. if (!rctIntersect.valid () || rctIntersect.empty ()) return;
  1055. PixelC* ppxlcRowStart1 = (PixelC*) pixels (rctIntersect.left, rctIntersect.top);
  1056. const PixelC* ppxlcRowStart2 = uci.pixels (rctIntersect.left, rctIntersect.top);
  1057. for (CoordI iy = rctIntersect.top; iy < rctIntersect.bottom; iy++)   {
  1058. PixelC* ppxlc1 = ppxlcRowStart1;
  1059. const PixelC* ppxlc2 = ppxlcRowStart2;
  1060. for (CoordI ix = rctIntersect.left; ix < rctIntersect.right; ix++) {
  1061. assert (*ppxlc1 == transpValue || *ppxlc1 == opaqueValue);
  1062. assert (*ppxlc2 == transpValue || *ppxlc2 == opaqueValue);
  1063. if (*ppxlc1 == *ppxlc2)
  1064. *ppxlc1 = (PixelC) transpValue;
  1065. else 
  1066. *ppxlc1 = (PixelC) opaqueValue;
  1067. ppxlc1++;
  1068. ppxlc2++;
  1069. }
  1070. ppxlcRowStart1 += where ().width;
  1071. ppxlcRowStart2 += uci.where ().width;
  1072. }
  1073. }
  1074. Void CU8Image::CU8Image_or (const CU8Image& uci)
  1075. {
  1076. CRct rctIntersect = m_rc;
  1077. rctIntersect.clip (uci.where());
  1078. if (!rctIntersect.valid () || rctIntersect.empty ()) return;
  1079. PixelC* ppxlcRowStart1 = (PixelC*) pixels (rctIntersect.left, rctIntersect.top);
  1080. const PixelC* ppxlcRowStart2 = uci.pixels (rctIntersect.left, rctIntersect.top);
  1081. for (CoordI iy = rctIntersect.top; iy < rctIntersect.bottom; iy++)   {
  1082. PixelC* ppxlc1 = ppxlcRowStart1;
  1083. const PixelC* ppxlc2 = ppxlcRowStart2;
  1084. for (CoordI ix = rctIntersect.left; ix < rctIntersect.right; ix++) {
  1085. assert (*ppxlc1 == transpValue || *ppxlc1 == opaqueValue);
  1086. assert (*ppxlc2 == transpValue || *ppxlc2 == opaqueValue);
  1087. if (*ppxlc2 == opaqueValue)
  1088. *ppxlc1 = opaqueValue;
  1089. ppxlc1++;
  1090. ppxlc2++;
  1091. }
  1092. ppxlcRowStart1 += where ().width;
  1093. ppxlcRowStart2 += uci.where ().width;
  1094. }
  1095. }
  1096. Void CU8Image::CU8Image_and (const CU8Image& uci)
  1097. {
  1098. CRct rctIntersect = m_rc;
  1099. rctIntersect.clip (uci.where());
  1100. if (!rctIntersect.valid () || rctIntersect.empty ()) return;
  1101. PixelC* ppxlcRowStart1 = (PixelC*) pixels (rctIntersect.left, rctIntersect.top);
  1102. const PixelC* ppxlcRowStart2 = uci.pixels (rctIntersect.left, rctIntersect.top);
  1103. for (CoordI iy = rctIntersect.top; iy < rctIntersect.bottom; iy++)   {
  1104. PixelC* ppxlc1 = ppxlcRowStart1;
  1105. const PixelC* ppxlc2 = ppxlcRowStart2;
  1106. for (CoordI ix = rctIntersect.left; ix < rctIntersect.right; ix++) {
  1107. assert (*ppxlc1 == transpValue || *ppxlc1 == opaqueValue);
  1108. assert (*ppxlc2 == transpValue || *ppxlc2 == opaqueValue);
  1109. if (*ppxlc2 == transpValue)
  1110. *ppxlc1 = transpValue;
  1111. ppxlc1++;
  1112. ppxlc2++;
  1113. }
  1114. ppxlcRowStart1 += where ().width;
  1115. ppxlcRowStart2 += uci.where ().width;
  1116. }
  1117. }
  1118. Void CU8Image::maskOut (const CU8Image& uci)
  1119. {
  1120. CRct rctIntersect = m_rc;
  1121. rctIntersect.clip (uci.where());
  1122. if (!rctIntersect.valid () || rctIntersect.empty ()) return;
  1123. PixelC* ppxlcRowStart = (PixelC*) pixels (rctIntersect.left, rctIntersect.top);
  1124. const PixelC* ppxlcRowStartMask = uci.pixels (rctIntersect.left, rctIntersect.top);
  1125. for (CoordI iy = rctIntersect.top; iy < rctIntersect.bottom; iy++)   {
  1126. PixelC* ppxlc = ppxlcRowStart;
  1127. const PixelC* ppxlcMask = ppxlcRowStartMask;
  1128. for (CoordI ix = rctIntersect.left; ix < rctIntersect.right; ix++) {
  1129. assert (*ppxlcMask == transpValue || *ppxlcMask == opaqueValue);
  1130. assert (*ppxlc == transpValue || *ppxlc == opaqueValue);
  1131. if (*ppxlcMask != transpValue)
  1132. *ppxlc = transpValue;
  1133. ppxlc++;
  1134. ppxlcMask++;
  1135. }
  1136. ppxlcRowStart += where ().width;
  1137. ppxlcRowStartMask += uci.where ().width;
  1138. }
  1139. }
  1140. Void CU8Image::mutiplyAlpha (const CU8Image& uci)
  1141. {
  1142. CRct rctIntersect = m_rc;
  1143. rctIntersect.clip (uci.where());
  1144. if (!rctIntersect.valid () || rctIntersect.empty ()) return;
  1145. PixelC* ppxlcRowStart = (PixelC*) pixels (rctIntersect.left, rctIntersect.top);
  1146. const PixelC* ppxlcRowStartMask = uci.pixels (rctIntersect.left, rctIntersect.top);
  1147. for (CoordI iy = rctIntersect.top; iy < rctIntersect.bottom; iy++)   {
  1148. PixelC* ppxlc = ppxlcRowStart;
  1149. const PixelC* ppxlcMask = ppxlcRowStartMask;
  1150. for (CoordI ix = rctIntersect.left; ix < rctIntersect.right; ix++) {
  1151. assert (*ppxlcMask == transpValue || *ppxlcMask == opaqueValue);
  1152. if (*ppxlcMask == transpValue)
  1153. *ppxlc = transpValue;
  1154. else
  1155. *ppxlc = (PixelC) ((*ppxlc * *ppxlcMask + 127) / opaqueValueF); //normalize
  1156. ppxlc++;
  1157. ppxlcMask++;
  1158. }
  1159. ppxlcRowStart += where ().width;
  1160. ppxlcRowStartMask += uci.where ().width;
  1161. }
  1162. }
  1163. Void CU8Image::cropOnAlpha ()
  1164. {
  1165. CRct rctVisible = whereVisible ();
  1166. where (rctVisible);
  1167. }
  1168. Void CU8Image::operator = (const CU8Image& uci)
  1169. {
  1170. delete [] m_ppxlc;
  1171. copyConstruct (uci, uci.where ());
  1172. }
  1173. Void CU8Image::decimateBinaryShapeFrom (const CU8Image& uciSrc)  // decimate by rateX and rateY in a conservative way
  1174. {
  1175. const CoordI left = uciSrc.where ().left / 2;
  1176. const CoordI top = uciSrc.where ().top / 2;
  1177. Int roundR = (uciSrc.where ().right >= 0) ? 1 : -1;
  1178. Int roundB = (uciSrc.where ().bottom >= 0) ? 1 : -1;
  1179. const CoordI right = (uciSrc.where ().right + roundR) / 2;
  1180. const CoordI bottom = (uciSrc.where ().bottom + roundB) / 2;
  1181. assert (where () == CRct (left, top, right, bottom));
  1182. PixelC* ppxlc = (PixelC*) pixels ();
  1183. const PixelC* ppxlcSrc11 = uciSrc.pixels ();
  1184. const PixelC* ppxlcSrc12 = ppxlcSrc11 + 1;
  1185. const PixelC* ppxlcSrc21 = ppxlcSrc11 + uciSrc.where ().width;
  1186. const PixelC* ppxlcSrc22 = ppxlcSrc21 + 1;
  1187. CoordI x, y;
  1188. for (y = top; y < bottom; y++) {
  1189. for (x = left; x < right; x++) {
  1190. assert (*ppxlcSrc11 == transpValue || *ppxlcSrc11 == opaqueValue);
  1191. assert (*ppxlcSrc12 == transpValue || *ppxlcSrc12 == opaqueValue);
  1192. assert (*ppxlcSrc21 == transpValue || *ppxlcSrc21 == opaqueValue);
  1193. assert (*ppxlcSrc22 == transpValue || *ppxlcSrc22 == opaqueValue);
  1194. *ppxlc++ = *ppxlcSrc11 | *ppxlcSrc12 | *ppxlcSrc21 | *ppxlcSrc22;
  1195. ppxlcSrc11 += 2;
  1196. ppxlcSrc12 += 2;
  1197. ppxlcSrc21 += 2;
  1198. ppxlcSrc22 += 2;
  1199. }
  1200. ppxlcSrc11 += uciSrc.where ().width;
  1201. ppxlcSrc12 += uciSrc.where ().width;
  1202. ppxlcSrc21 += uciSrc.where ().width;
  1203. ppxlcSrc22 += uciSrc.where ().width;
  1204. }
  1205. }
  1206. Bool CU8Image::operator == (const CU8Image& uci) const
  1207. {
  1208. if (uci.where () != where ())
  1209. return FALSE;
  1210. UInt area = where ().area ();
  1211. const PixelC* ppxlc = uci.pixels ();
  1212. const PixelC* ppxlcThis = pixels ();
  1213. for (UInt ip = 0; ip < area; ip++, ppxlc++, ppxlcThis++)
  1214. if (*ppxlc != *ppxlcThis)
  1215. return FALSE;
  1216. return TRUE;
  1217. }
  1218. Double CU8Image::mse (const CU8Image& uciCompare) const
  1219. {
  1220. assert (uciCompare.where () == where ());
  1221. Int sqr = 0;
  1222. const PixelC* ppxlcThis = pixels ();
  1223. const PixelC* ppxlcCompare = uciCompare.pixels ();
  1224. UInt area = where ().area ();
  1225. for (UInt i = 0; i < area; i++) {
  1226. Int diffR = *ppxlcThis - *ppxlcCompare;
  1227. sqr += diffR * diffR;
  1228. ppxlcThis++;
  1229. ppxlcCompare++;
  1230. }
  1231. return ((Double) sqr / area);
  1232. }
  1233. Double CU8Image::mse (const CU8Image& uciCompare, const CU8Image& uciMsk) const
  1234. {
  1235. assert (uciCompare.where () == where () && uciMsk.where () == where ());
  1236. Int sqr = 0;
  1237. const PixelC* ppxlcThis = pixels ();
  1238. const PixelC* ppxlcCompare = uciCompare.pixels ();
  1239. const PixelC* ppxlcMsk = uciMsk.pixels ();
  1240. UInt area = where ().area ();
  1241. UInt uiNonTransp = 0;
  1242. for (UInt i = 0; i < area; i++) {
  1243. if (*ppxlcMsk != transpValue) {
  1244. Int diffR = *ppxlcThis - *ppxlcCompare;
  1245. sqr += diffR * diffR;
  1246. uiNonTransp++;
  1247. }
  1248. ppxlcThis++;
  1249. ppxlcCompare++;
  1250. ppxlcMsk++;
  1251. }
  1252. if (uiNonTransp == 0) 
  1253. return 0.0;
  1254. return ((Double) sqr / area);
  1255. }
  1256. Double CU8Image::snr (const CU8Image& uciCompare) const
  1257. {
  1258. Double msError = mse (uciCompare);
  1259. if (msError == 0.0)
  1260. return 1000000.0;
  1261. else 
  1262. return (log10 (255 * 255 / msError) * 10.0);
  1263. }
  1264. Double CU8Image::snr (const CU8Image& uciCompare, const CU8Image& uciMsk) const
  1265. {
  1266. CU8Image* puciMskOp = NULL;
  1267. Double msError = 0;
  1268. if (&uciMsk == NULL) {
  1269. puciMskOp = new CU8Image (where (), (PixelC) opaqueValue);
  1270. msError = mse (uciCompare, *puciMskOp);
  1271. delete puciMskOp;
  1272. }
  1273. else
  1274. msError = mse (uciCompare, uciMsk);
  1275. if (msError == 0.0)
  1276. return 1000000.0;
  1277. else 
  1278. return (log10 (255 * 255 / msError) * 10.0);
  1279. }
  1280. // vdldump doesnt work for >8bit video
  1281. Void CU8Image::vdlDump (const Char* fileName, const CRct& rct) const
  1282. {
  1283. CRct rctRegionOfInterest = (!rct.valid ()) ? where () : rct;
  1284. assert (rctRegionOfInterest <= where ());
  1285. if (rctRegionOfInterest == where ()) {
  1286. CVideoObjectPlane vop (where (), opaquePixel);
  1287. CPixel* ppxl = (CPixel*) vop.pixels ();
  1288. const PixelC* ppxlc = pixels ();
  1289. UInt area = where ().area ();
  1290. for (UInt ip = 0; ip < area; ip++, ppxl++, ppxlc++)
  1291. *ppxl = CPixel ((U8)*ppxlc, (U8)*ppxlc, (U8)*ppxlc, opaqueValue);
  1292. vop.vdlDump (fileName);
  1293. }
  1294. else {
  1295. CVideoObjectPlane vop (rct, opaquePixel);
  1296. Int offset = where ().width - rct.width;
  1297. CPixel* ppxl = (CPixel*) vop.pixels ();
  1298. const PixelC* ppxlc = pixels (rctRegionOfInterest.left, rctRegionOfInterest.top);
  1299. for (CoordI y = rctRegionOfInterest.top; y < rctRegionOfInterest.bottom; y++) {
  1300. for (CoordI x = rctRegionOfInterest.left; x < rctRegionOfInterest.right; x++, ppxl++, ppxlc++) {
  1301. *ppxl = CPixel ((U8)*ppxlc, (U8)*ppxlc, (U8)*ppxlc, opaqueValue);
  1302. }
  1303. ppxlc += offset;
  1304. }
  1305. vop.vdlDump (fileName);
  1306. }
  1307. }
  1308. Void CU8Image::dump (FILE* pf, const CRct& rct, Int iScale) const
  1309. {
  1310. CRct rctRegionOfInterest = (!rct.valid ()) ? where () : rct;
  1311. assert (rctRegionOfInterest <= where ());
  1312. iScale++;
  1313. if(iScale!=256)
  1314. {
  1315. Int i,j;
  1316. PixelC pxlTmp;
  1317. const PixelC* ppxlc = pixels (rctRegionOfInterest.left, rctRegionOfInterest.top);
  1318. for (i = rctRegionOfInterest.top; i < rctRegionOfInterest.bottom; i++) {
  1319. for(j = 0; j <rctRegionOfInterest.width; j++)
  1320. {
  1321. pxlTmp = (ppxlc[j]*iScale)>>8;
  1322. fwrite(&pxlTmp, sizeof(PixelC), 1, pf);
  1323. }
  1324. ppxlc += where ().width;
  1325. }
  1326. }
  1327. else
  1328. {
  1329. if (rctRegionOfInterest == where ()) {
  1330. /* NBIT: change U8 to PixelC
  1331. fwrite (m_ppxlc, sizeof (U8), where ().area (), pf);
  1332. */
  1333. fwrite (m_ppxlc, sizeof (PixelC), where ().area (), pf);
  1334. } else {
  1335. const PixelC* ppxlc = pixels (rctRegionOfInterest.left, rctRegionOfInterest.top);
  1336. for (Int i = rctRegionOfInterest.top; i < rctRegionOfInterest.bottom; i++) {
  1337. /* NBIT: change U8 to PixelC
  1338. fwrite (ppxlc, sizeof (U8), rctRegionOfInterest.width, pf);
  1339. */
  1340. fwrite (ppxlc, sizeof (PixelC), rctRegionOfInterest.width, pf);
  1341. ppxlc += where ().width;
  1342. }
  1343. }
  1344. }
  1345. }
  1346. Void CU8Image::dumpWithMask (FILE* pf, const CU8Image *puciMask, const CRct& rct, Int iScale) const
  1347. {
  1348. PixelC pxlZero = 0; // NBIT
  1349. PixelC pxlTmp;
  1350. CRct rctRegionOfInterest = (!rct.valid ()) ? where () : rct;
  1351. assert (rctRegionOfInterest <= where ());
  1352. assert (rctRegionOfInterest <= puciMask->where ());
  1353. Int x;
  1354. const PixelC* ppxlc = pixels (rctRegionOfInterest.left, rctRegionOfInterest.top);
  1355. const PixelC* ppxlcMask = puciMask->pixels(rctRegionOfInterest.left, rctRegionOfInterest.top);
  1356. iScale++;
  1357. for (Int i = rctRegionOfInterest.top; i < rctRegionOfInterest.bottom; i++) {
  1358. for(x = 0; x<rctRegionOfInterest.width; x++)
  1359. if(ppxlcMask[x] == 0)
  1360. /* NBIT: change
  1361. fputc(0, pf);
  1362. */
  1363. fwrite(&pxlZero, sizeof(PixelC), 1, pf);
  1364. else if(iScale==256)
  1365. /* NBIT: change
  1366. fputc(ppxlc[x], pf);
  1367. */
  1368. fwrite(&ppxlc[x], sizeof(PixelC), 1, pf);
  1369. else
  1370. {
  1371. pxlTmp = (ppxlc[x] * iScale)>>8;
  1372. fwrite(&pxlTmp, sizeof(PixelC), 1, pf);
  1373. }
  1374. ppxlc += where ().width;
  1375. ppxlcMask += puciMask->where().width;
  1376. }
  1377. }
  1378. Void CU8Image::txtDump (const Char* fileName) const
  1379. {
  1380. FILE* pfTxt;
  1381. const PixelC* ppxlc = pixels ();
  1382. if (fileName != NULL)
  1383. pfTxt = fopen (fileName, "w");
  1384. else
  1385. pfTxt = NULL;
  1386. for (CoordI y = 0; y < where ().height (); y++) {
  1387. for (CoordI x = 0; x < where ().width; x++) {
  1388. if (pfTxt != NULL)
  1389. fprintf (pfTxt, "%3d  ", *ppxlc);
  1390. else
  1391. printf ("%3d  ", *ppxlc);
  1392. ppxlc++;
  1393. }
  1394. if (pfTxt != NULL)
  1395. fprintf (pfTxt, "n");
  1396. else
  1397. printf ("n");
  1398. }
  1399. if (pfTxt != NULL)
  1400. fclose (pfTxt);
  1401. }
  1402. Void CU8Image::txtDump (FILE *pf) const
  1403. {
  1404. const PixelC *ppxlc = pixels();
  1405. for (CoordI y = 0; y < where ().height (); y++) {
  1406. for (CoordI x = 0; x < where ().width; x++) {
  1407. fprintf (pf, "%3d ", *ppxlc);
  1408. ppxlc++;
  1409. }
  1410. fprintf (pf,"n");
  1411. }
  1412. fprintf (pf,"n");
  1413. }
  1414. Void CU8Image::txtDumpMask (FILE *pf) const
  1415. {
  1416. const PixelC *ppxlc = pixels ();
  1417. for (CoordI y = 0; y < where ().height (); y++) {
  1418. for (CoordI x = 0; x < where ().width; x++) {
  1419. if (*ppxlc == transpValue)
  1420. fprintf (pf, "..");
  1421. else
  1422. fprintf (pf, "[]");
  1423. ppxlc++;
  1424. }
  1425. fprintf (pf,"n");
  1426. }
  1427. fprintf (pf,"n");
  1428. }