PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/common/video/iso-mpeg4/src/type_warp.cpp

https://github.com/stsquad/mpeg4ip
C++ | 438 lines | 334 code | 57 blank | 47 comment | 51 complexity | 2d0a49bad39d3015395a6ad527474369 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.0
  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. and also edited by
  9. Yuichiro Nakaya (Hitachi, Ltd.)
  10. Yoshinori Suzuki (Hitachi, Ltd.)
  11. in the course of development of the MPEG-4 Video (ISO/IEC 14496-2).
  12. This software module is an implementation of a part of one or more MPEG-4 Video tools
  13. as specified by the MPEG-4 Video.
  14. ISO/IEC gives users of the MPEG-4 Video free license to this software module or modifications
  15. thereof for use in hardware or software products claiming conformance to the MPEG-4 Video.
  16. Those intending to use this software module in hardware or software products are advised that its use may infringe existing patents.
  17. The original developer of this software module and his/her company,
  18. the subsequent editors and their companies,
  19. and ISO/IEC have no liability for use of this software module or modifications thereof in an implementation.
  20. Copyright is not released for non MPEG-4 Video conforming products.
  21. Microsoft retains full right to use the code for his/her own purpose,
  22. assign or donate the code to a third party and to inhibit third parties from using the code for non <MPEG standard> conforming products.
  23. This copyright notice must be included in all copies or derivative works.
  24. Copyright (c) 1996, 1997.
  25. Module Name:
  26. warp.cpp
  27. Abstract:
  28. Geometry transformation:
  29. 2D Affine
  30. 2D Perspective
  31. Revision History:
  32. Jan. 13, 1999: Code for disallowing zero demoninators in perspective
  33. warping added by Hitachi, Ltd.
  34. *************************************************************************/
  35. #include <math.h>
  36. #include "basic.hpp"
  37. #include "svd.h"
  38. #include "warp.hpp"
  39. #ifdef __MFC_
  40. #ifdef _DEBUG
  41. #undef THIS_FILE
  42. static char BASED_CODE THIS_FILE[] = __FILE__;
  43. #endif
  44. #define new DEBUG_NEW
  45. #endif // __MFC_
  46. CVector2D CMatrix2x2D::apply (const CVector2D& v) const
  47. {
  48. return CVector2D (
  49. m_value [0] [0] * v.x + m_value [0] [1] * v.y,
  50. m_value [1] [0] * v.x + m_value [1] [1] * v.y
  51. );
  52. }
  53. CMatrix2x2D::CMatrix2x2D (Double d)
  54. {
  55. m_value [0] [0] = d;
  56. m_value [1] [1] = d;
  57. m_value [0] [1] = 0;
  58. m_value [1] [0] = 0;
  59. }
  60. CMatrix2x2D::CMatrix2x2D (Double d00, Double d01, Double d10, Double d11)
  61. {
  62. m_value [0] [0] = d00;
  63. m_value [1] [1] = d11;
  64. m_value [0] [1] = d01;
  65. m_value [1] [0] = d10;
  66. }
  67. CMatrix2x2D::CMatrix2x2D (const CVector2D& v0, const CVector2D& v1, Bool fAsColumns)
  68. {
  69. m_value [0] [0] = v0.x;
  70. m_value [1] [0] = v0.y;
  71. m_value [0] [1] = v1.x;
  72. m_value [1] [1] = v1.y;
  73. if (!fAsColumns) transpose ();
  74. }
  75. CMatrix2x2D::CMatrix2x2D (const CVector2D v [2])
  76. {
  77. *this = CMatrix2x2D (v [0], v [1]);
  78. }
  79. CMatrix2x2D CMatrix2x2D::operator * (const CMatrix2x2D& x) const
  80. {
  81. CMatrix2x2D r;
  82. r.m_value [0] [0] = m_value [0] [0] * x.m_value [0] [0] + m_value [0] [1] * x.m_value [1] [0];
  83. r.m_value [1] [0] = m_value [1] [0] * x.m_value [0] [0] + m_value [1] [1] * x.m_value [1] [0];
  84. r.m_value [0] [1] = m_value [0] [0] * x.m_value [0] [1] + m_value [0] [1] * x.m_value [1] [1];
  85. r.m_value [1] [1] = m_value [1] [0] * x.m_value [0] [1] + m_value [1] [1] * x.m_value [1] [1];
  86. return r;
  87. }
  88. CMatrix2x2D::CMatrix2x2D (const CVector2D& s0, const CVector2D& s1, const CVector2D& d0, const CVector2D& d1)
  89. {
  90. *this = CMatrix2x2D (d0, d1) * CMatrix2x2D (s0, s1).inverse ();
  91. }
  92. CMatrix2x2D::CMatrix2x2D (const CVector2D source [2], const CVector2D dest [2])
  93. {
  94. *this = CMatrix2x2D (source [0], source [1], dest [0], dest [1]);
  95. }
  96. CMatrix2x2D CMatrix2x2D::inverse () const
  97. {
  98. Double det = determinant ();
  99. if (det == 0) // ill conditioned -- make this a better test
  100. {
  101. return CMatrix2x2D ((Double) 0);
  102. }
  103. CMatrix2x2D r;
  104. Double detInv = (Double) 1.0 / det;
  105. r.m_value [0] [0] = m_value [1] [1] * detInv;
  106. r.m_value [1] [1] = m_value [0] [0] * detInv;
  107. r.m_value [0] [1] = - m_value [0] [1] * detInv;
  108. r.m_value [1] [0] = - m_value [1] [0] * detInv;
  109. return r;
  110. }
  111. Void CMatrix2x2D::transpose ()
  112. {
  113. Double tmp = m_value [0] [1];
  114. m_value [0] [1] = m_value [1] [0];
  115. m_value [1] [0] = tmp;
  116. }
  117. CAffine2D::CAffine2D (const CSiteD& source, const CSiteD& dest) :
  118. m_mtx(1.), m_stdSrc (source), m_stdDst (dest)
  119. {
  120. // thats all folks
  121. }
  122. CAffine2D::CAffine2D (const CSiteD& s0, const CSiteD& s1, const CSiteD& d0, const CSiteD& d1) :
  123. m_mtx(s1 - s0, (s1 - s0).rot90 (), d1 - d0, (d1 - d0).rot90 ()),
  124. m_stdSrc (s0),
  125. m_stdDst (d0)
  126. {
  127. }
  128. CAffine2D::CAffine2D (
  129. const CSiteD& s, const CVector2D& sv0, const CVector2D& sv1,
  130. const CSiteD& d, const CVector2D& dv0, const CVector2D& dv1) :
  131. m_mtx(sv0, sv1, dv0, dv1), m_stdSrc (s), m_stdDst (d)
  132. {
  133. }
  134. CAffine2D::CAffine2D (const CSiteD source [3], const CSiteD dest [3]) :
  135. m_mtx (
  136. source [1] - source [0],
  137. source [2] - source [0],
  138. dest [1] - dest [0],
  139. dest [2] - dest [0]
  140. ),
  141. m_stdSrc (source [0]),
  142. m_stdDst (dest [0])
  143. {
  144. }
  145. CAffine2D::CAffine2D (const CoordD params [6]) :
  146. m_mtx (CVector2D (params [0], params [3]), CVector2D (params [1], params [4])),
  147. m_stdSrc (0, 0),
  148. m_stdDst (params [2], params [5])
  149. {
  150. }
  151. CAffine2D CAffine2D::inverse () const
  152. {
  153. CAffine2D affInv;
  154. affInv.m_mtx= m_mtx.inverse ();
  155. affInv.m_stdSrc = m_stdDst;
  156. affInv.m_stdDst = m_stdSrc;
  157. return affInv;
  158. }
  159. CAffine2D CAffine2D::setOrigin (const CSiteD& std) const
  160. {
  161. CAffine2D r;
  162. CVector2D vec;
  163. r.m_mtx = m_mtx;
  164. vec = m_mtx.apply (std - m_stdDst);
  165. r.m_stdDst.x = std.x - vec.x;
  166. r.m_stdDst.y = std.y - vec.y;
  167. r.m_stdSrc = m_stdSrc;
  168. return r;
  169. }
  170. Void CAffine2D::getParams (CoordD params [6]) const
  171. {
  172. params [0] = m_mtx.element (0, 0);
  173. params [1] = m_mtx.element (0, 1);
  174. params [3] = m_mtx.element (1, 0);
  175. params [4] = m_mtx.element (1, 1);
  176. params [2] = m_stdDst.x - params [0] * m_stdSrc.x - params [1] * m_stdSrc.y;
  177. params [5] = m_stdDst.y - params [3] * m_stdSrc.x - params [4] * m_stdSrc.y;
  178. }
  179. CPerspective2D::~CPerspective2D ()
  180. {
  181. delete [] m_rgCoeff;
  182. }
  183. CPerspective2D::CPerspective2D ()
  184. {
  185. m_rgCoeff = NULL;
  186. }
  187. CPerspective2D::CPerspective2D (const UInt pntNum, const CSiteD source [4], const CSiteD dest [4], const UInt accuracy) : m_rgCoeff (NULL)
  188. {
  189. UInt uiScale = 1 << (accuracy + 1);
  190. m_x0 = source [0].x;
  191. m_y0 = source [0].y;
  192. m_rgCoeff = new Double [9];
  193. Double x [4], dx [4], y [4], dy [4], a[4][4];
  194. memset(a, 0, sizeof(a));
  195. for (UInt k = 0; k < pntNum; k++) {
  196. m_rgstdSrc [k] = source [k];
  197. m_rgstdDst [k] = dest [k] * uiScale;
  198. x [k] = m_rgstdDst [k].x;
  199. y [k] = m_rgstdDst [k].y;
  200. }
  201. Int width = (Int) (m_rgstdSrc [1].x - m_rgstdSrc [0].x);
  202. Int height = (Int) (m_rgstdSrc [2].y - m_rgstdSrc [0].y);
  203. if (pntNum == 1) {
  204. a[1][1] = (Double) uiScale;
  205. a[2][1] = 0;
  206. a[3][1] = x [0];
  207. a[1][2] = 0;
  208. a[2][2] = (Double) uiScale;
  209. a[3][2] = y [0];
  210. a[1][3] = 0;
  211. a[2][3] = 0;
  212. a[3][3] = 1.0;
  213. } else if (pntNum == 2) {
  214. a[1][1] = (x [1] - x [0]) ;
  215. a[2][1] = (y [0] - y [1]) ;
  216. a[3][1] = x [0] * width;
  217. a[1][2] = (y [1] - y [0]) ;
  218. a[2][2] = (x [1] - x [0]) ;
  219. a[3][2] = y [0] * width;
  220. a[1][3] = 0;
  221. a[2][3] = 0;
  222. a[3][3] = width;
  223. } else if (pntNum == 3) {
  224. a[1][1] = (x [1] - x [0]) * height;
  225. a[2][1] = (x [2] - x [0]) * width;
  226. a[3][1] = x [0] * height * width;
  227. a[1][2] = (y [1] - y [0]) * height;
  228. a[2][2] = (y [2] - y [0]) * width;
  229. a[3][2] = y [0] * height * width;
  230. a[1][3] = 0;
  231. a[2][3] = 0;
  232. a[3][3] = height * width;
  233. } else if (pntNum == 4) {
  234. dx [1] = x [1] - x [3]; dx [2] = x [2] - x [3]; dx [3] = x [0] - x [1] + x [3] - x [2];
  235. dy [1] = y [1] - y [3]; dy [2] = y [2] - y [3]; dy [3] = y [0] - y [1] + y [3] - y [2];
  236. if ((dx [3] == 0 && dy [3] == 0) || pntNum == 3) {
  237. a[1][1] = (x [1] - x [0]) * height;
  238. a[2][1] = (x [2] - x [0]) * width;
  239. a[3][1] = x [0] * height * width;
  240. a[1][2] = (y [1] - y [0]) * height;
  241. a[2][2] = (y [2] - y [0]) * width;
  242. a[3][2] = y [0] * height * width;
  243. a[1][3] = 0;
  244. a[2][3] = 0;
  245. a[3][3] = height * width;
  246. } else {
  247. Double deltaD = dx [1] * dy [2] - dx [2] * dy [1];
  248. a[1][3] = (dx [3] * dy [2] - dx [2] * dy [3]) * height;
  249. a[2][3] = (dx [1] * dy [3] - dx [3] * dy [1]) * width;
  250. a[1][1] = (x [1] - x [0]) * height * deltaD + a[1][3] * x [1];
  251. a[2][1] = (x [2] - x [0]) * width * deltaD + a[2][3] * x [2];
  252. a[3][1] = x [0] * height * width * deltaD;
  253. a[1][2] = (y [1] - y [0]) * deltaD * height + a[1][3] * y [1];
  254. a[2][2] = (y [2] - y [0]) * deltaD * width + a[2][3] * y [2];
  255. a[3][2] = y [0] * height * width * deltaD;
  256. a[3][3] = height * width * deltaD;
  257. }
  258. }
  259. m_rgCoeff [0] = a[1][1];
  260. m_rgCoeff [1] = a[2][1];
  261. m_rgCoeff [2] = a[3][1];
  262. m_rgCoeff [3] = a[1][2];
  263. m_rgCoeff [4] = a[2][2];
  264. m_rgCoeff [5] = a[3][2];
  265. m_rgCoeff [6] = a[1][3];
  266. m_rgCoeff [7] = a[2][3];
  267. m_rgCoeff [8] = a[3][3];
  268. }
  269. CPerspective2D::CPerspective2D (const CSiteD source [4], const CSiteD dest [4]) : m_rgCoeff (NULL)
  270. {
  271. m_x0 = m_y0 = 0.0;
  272. UInt pts = 4;
  273. UInt rows = 2 * pts, cols = 8, i, j;
  274. for (i = 0; i < 4; i++) {
  275. m_rgstdSrc [i] = source [i];
  276. m_rgstdDst [i] = dest [i];
  277. }
  278. Double* B = new Double [rows];
  279. Double** A = (Double**) new Double* [rows];
  280. for (i = 0; i < rows; i++)
  281. A [i] = new Double [cols] ;
  282. for (i = 0; i < pts; i++) {
  283. A [i] [0] = m_rgstdSrc [i].x ;
  284. A [i] [1] = m_rgstdSrc [i].y ;
  285. A [i] [2] = 1;
  286. A [i] [3] = A [i] [4] = A[i] [5] =0;
  287. A [i] [6] = (-1) * (m_rgstdSrc [i].x * m_rgstdDst [i].x );
  288. A [i] [7] = (-1) * (m_rgstdSrc [i].y * m_rgstdDst [i].x );
  289. B [i] = m_rgstdDst [i].x;
  290. }
  291. for (i = pts, j = 0; i < rows; i++, j++) {
  292. A [i] [0] = A [i] [1] = A [i] [2] = 0;
  293. A [i] [3] = m_rgstdSrc [j].x ;
  294. A [i] [4] = m_rgstdSrc [j].y ;
  295. A [i] [5] = 1;
  296. A [i] [6] = (-1) * (m_rgstdSrc [j].x * m_rgstdDst [j].y);
  297. A [i] [7] = (-1) * (m_rgstdSrc [j].y * m_rgstdDst [j].y);
  298. B [i] = m_rgstdDst [j].y;
  299. }
  300. m_rgCoeff = linearLS (A, B, rows, cols);
  301. delete [] B;
  302. for (i = 0; i < rows; i++)
  303. delete [] A [i];
  304. delete [] A;
  305. }
  306. CPerspective2D::CPerspective2D (Double* rgCoeff) : m_rgCoeff (NULL)
  307. {
  308. m_rgCoeff = new Double [8];
  309. UInt i;
  310. for (i = 0; i < 8; i++)
  311. m_rgCoeff [i] = rgCoeff [i];
  312. m_rgstdSrc [0] = CSiteD (0, 0);
  313. m_rgstdSrc [1] = CSiteD (176, 0);
  314. m_rgstdSrc [2] = CSiteD (0, 144);
  315. m_rgstdSrc [3] = CSiteD (176, 144);
  316. for (i = 0; i < 4; i++) {
  317. m_rgstdDst [i] = (*this * m_rgstdSrc [i]).s;
  318. }
  319. }
  320. CSiteDWFlag CPerspective2D::apply (const CSiteD& s0) const
  321. {
  322. Double destX, destY, destW;
  323. CSiteDWFlag destST;
  324. destX = (s0.x - m_x0) * m_rgCoeff [0] + (s0.y - m_y0) * m_rgCoeff [1] + m_rgCoeff [2];
  325. destY = (s0.x - m_x0 ) * m_rgCoeff [3] + (s0.y - m_y0 ) * m_rgCoeff [4] + m_rgCoeff [5];
  326. destW = (s0.x - m_x0) * m_rgCoeff [6] + (s0.y - m_y0) * m_rgCoeff [7] + m_rgCoeff [8];
  327. if (destW != 0.0) {
  328. destST.s.x = destX / destW;
  329. destST.s.y = destY / destW;
  330. destST.f = FALSE;
  331. } else // destW == 0.0
  332. destST.f = TRUE;
  333. return destST;
  334. }
  335. CSiteWFlag CPerspective2D::apply (const CSite& s0) const
  336. {
  337. Double destX, destY, destW;
  338. CSiteWFlag destST;
  339. destX = (s0.x - m_x0) * m_rgCoeff [0] + (s0.y - m_y0) * m_rgCoeff [1] + m_rgCoeff [2];
  340. destY = (s0.x - m_x0 ) * m_rgCoeff [3] + (s0.y - m_y0 ) * m_rgCoeff [4] + m_rgCoeff [5];
  341. destW = (s0.x - m_x0) * m_rgCoeff [6] + (s0.y - m_y0) * m_rgCoeff [7] + m_rgCoeff [8];
  342. if (destW != 0.0) {
  343. if ((destX >= 0 && destW > 0) || (destX <= 0 && destW < 0)) {
  344. destST.s.x = (CoordI) ((destX + destW / 2) / destW);
  345. } else {
  346. if (destX > 0 && destW < 0) {
  347. destST.s.x = (CoordI) ((destX - (destW + 1) / 2) / destW);
  348. } else {
  349. destST.s.x = (CoordI) ((destX - (destW - 1) / 2) / destW);
  350. }
  351. }
  352. if ((destY >= 0 && destW > 0) || (destY <= 0 && destW < 0)) {
  353. destST.s.y = (CoordI) ((destY + destW / 2) / destW);
  354. } else {
  355. if (destY > 0 && destW < 0) {
  356. destST.s.y = (CoordI) ((destY - (destW + 1) / 2) / destW);
  357. } else {
  358. destST.s.y = (CoordI) ((destY - (destW - 1) / 2) / destW);
  359. }
  360. }
  361. destST.f = FALSE;
  362. } else // destW == 0.0
  363. destST.f = TRUE;
  364. return destST;
  365. }
  366. CPerspective2D CPerspective2D::inverse () const
  367. {
  368. return CPerspective2D (m_rgstdDst, m_rgstdSrc);
  369. }