1 /* ***** BEGIN LICENSE BLOCK ***** 2 * This file is part of openfx-misc <https://github.com/devernay/openfx-misc>, 3 * Copyright (C) 2013-2018 INRIA 4 * 5 * openfx-misc is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * openfx-misc is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with openfx-misc. If not, see <http://www.gnu.org/licenses/gpl-2.0.html> 17 * ***** END LICENSE BLOCK ***** */ 18 19 #ifndef DistortionModels_h 20 #define DistortionModels_h 21 22 #include "ofxCore.h" 23 #include "ofxsMacros.h" 24 25 OFXS_NAMESPACE_OFX_ENTER 26 27 // a generic distortion model abstract class (distortion parameters are added by the derived class) 28 class DistortionModel 29 { 30 protected: DistortionModel()31 DistortionModel() {}; 32 33 public: ~DistortionModel()34 virtual ~DistortionModel() {}; 35 36 private: // noncopyable 37 DistortionModel( const DistortionModel& ); 38 DistortionModel& operator=( const DistortionModel& ); 39 40 public: 41 // function used to distort a point or undistort an image 42 virtual void distort(double xu, double yu, double* xd, double *yd) const = 0; 43 44 // function used to undistort a point or distort an image 45 virtual void undistort(double xd, double yd, double* xu, double *yu) const = 0; 46 }; 47 48 // a distortion model class where ony the undistort function is given, and distort is solved by Newton 49 class DistortionModelUndistort 50 : public DistortionModel 51 { 52 protected: DistortionModelUndistort()53 DistortionModelUndistort() {}; 54 ~DistortionModelUndistort()55 virtual ~DistortionModelUndistort() {}; 56 57 private: 58 // function used to distort a point or undistort an image 59 virtual void distort(const double xu, 60 const double yu, 61 double* xd, 62 double *yd) const OVERRIDE FINAL; 63 64 // function used to undistort a point or distort an image 65 virtual void undistort(double xd, double yd, double* xu, double *yu) const OVERRIDE = 0; 66 }; 67 68 // a distortion model class where ony the distort function is given, and undistort is solved by Newton 69 class DistortionModelDistort 70 : public DistortionModel 71 { 72 protected: DistortionModelDistort()73 DistortionModelDistort() {}; 74 ~DistortionModelDistort()75 virtual ~DistortionModelDistort() {}; 76 77 private: 78 // function used to distort a point or undistort an image 79 virtual void distort(const double xu, 80 const double yu, 81 double* xd, 82 double *yd) const OVERRIDE = 0; 83 84 // function used to undistort a point or distort an image 85 virtual void undistort(double xd, double yd, double* xu, double *yu) const OVERRIDE FINAL; 86 }; 87 88 class DistortionModelNuke 89 : public DistortionModelUndistort 90 { 91 public: 92 DistortionModelNuke(const OfxRectD& format, 93 double par, 94 double k1, 95 double k2, 96 double cx, 97 double cy, 98 double squeeze, 99 double ax, 100 double ay); 101 ~DistortionModelNuke()102 virtual ~DistortionModelNuke() {}; 103 104 private: 105 // function used to undistort a point or distort an image 106 // (xd,yd) = 0,0 at the bottom left of the bottomleft pixel 107 virtual void undistort(double xd, double yd, double* xu, double *yu) const OVERRIDE FINAL; 108 109 double _par; 110 double _f; 111 double _xSrcCenter; 112 double _ySrcCenter; 113 double _k1; 114 double _k2; 115 double _cx; 116 double _cy; 117 double _squeeze; 118 double _ax; 119 double _ay; 120 }; 121 122 123 124 class DistortionModelPFBarrel 125 : public DistortionModelUndistort 126 { 127 public: 128 DistortionModelPFBarrel(const OfxRectD& format, 129 const OfxPointD& renderScale, 130 double c3, 131 double c5, 132 double xp, 133 double yp, 134 double squeeze); 135 ~DistortionModelPFBarrel()136 virtual ~DistortionModelPFBarrel() {}; 137 138 private: 139 // function used to undistort a point or distort an image 140 // (xd,yd) = 0,0 at the bottom left of the bottomleft pixel 141 virtual void undistort(double xd, double yd, double* xu, double *yu) const OVERRIDE FINAL; 142 143 OfxPointD _rs; 144 double _c3; 145 double _c5; 146 double _xp; 147 double _yp; 148 double _squeeze; 149 double _normx; 150 double _fw, _fh; 151 }; 152 153 154 155 /////////////////////// 3DEqualizer 156 157 158 /// this base class handles the 4 fov parameters & the seven built-in parameters 159 class DistortionModel3DEBase 160 : public DistortionModelUndistort 161 { 162 protected: 163 DistortionModel3DEBase(const OfxRectD& format, 164 const OfxPointD& renderScale, 165 double xa_fov_unit, 166 double ya_fov_unit, 167 double xb_fov_unit, 168 double yb_fov_unit, 169 double fl_cm, 170 double fd_cm, 171 double w_fb_cm, 172 double h_fb_cm, 173 double x_lco_cm, 174 double y_lco_cm, 175 double pa); 176 ~DistortionModel3DEBase()177 virtual ~DistortionModel3DEBase() {}; 178 179 // the following must be implemented by each model, and corresponds to operator () in ldpk 180 // Remove distortion. p is a point in diagonally normalized coordinates. 181 virtual void undistort_dn(double xd, double yd, double* xu, double *yu) const = 0; 182 183 private: 184 // function used to undistort a point or distort an image 185 // (xd,yd) = 0,0 at the bottom left of the bottomleft pixel undistort(double xd,double yd,double * xu,double * yu)186 virtual void undistort(double xd, double yd, double* xu, double *yu) const OVERRIDE FINAL 187 { 188 OfxPointD p_pix = {xd, yd}; 189 OfxPointD p_dn; 190 map_pix_to_dn(p_pix, &p_dn); 191 OfxPointD p_dn_u; 192 undistort_dn(p_dn.x, p_dn.y, &p_dn_u.x, &p_dn_u.y); 193 map_dn_to_pix(p_dn_u, &p_pix); 194 *xu = p_pix.x; 195 *yu = p_pix.y; 196 } 197 198 private: 199 void map_pix_to_dn(const OfxPointD & p_pix,OfxPointD * p_dn)200 map_pix_to_dn(const OfxPointD& p_pix, OfxPointD* p_dn) const 201 { 202 OfxPointD p_unit; 203 map_pix_to_unit(p_pix, &p_unit); 204 map_unit_to_dn(p_unit, p_dn); 205 } 206 207 // The result already contains the (half,half) shift. 208 void map_dn_to_pix(const OfxPointD & p_dn,OfxPointD * p_pix)209 map_dn_to_pix(const OfxPointD& p_dn, OfxPointD* p_pix) const 210 { 211 OfxPointD p_unit; 212 map_dn_to_unit(p_dn, &p_unit); 213 map_unit_to_pix(p_unit, p_pix); 214 } 215 216 void map_unit_to_dn(const OfxPointD & p_unit,OfxPointD * p_dn)217 map_unit_to_dn(const OfxPointD& p_unit, OfxPointD* p_dn) const 218 { 219 double p_cm_x = (p_unit.x - 1.0/2.0) * _w_fb_cm - _x_lco_cm; 220 double p_cm_y = (p_unit.y - 1.0/2.0) * _h_fb_cm - _y_lco_cm; 221 p_dn->x = p_cm_x / _r_fb_cm; 222 p_dn->y = p_cm_y / _r_fb_cm; 223 } 224 225 void map_dn_to_unit(const OfxPointD & p_dn,OfxPointD * p_unit)226 map_dn_to_unit(const OfxPointD& p_dn, OfxPointD* p_unit) const 227 { 228 double p_cm_x = p_dn.x * _r_fb_cm + _w_fb_cm / 2 + _x_lco_cm; 229 double p_cm_y = p_dn.y * _r_fb_cm + _h_fb_cm / 2 + _y_lco_cm; 230 p_unit->x = p_cm_x / _w_fb_cm; 231 p_unit->y = p_cm_y / _h_fb_cm; 232 } 233 234 #if 0 235 // the following twho funcs are for when 0,0 is the center of the bottomleft pixel (see nuke plugin) 236 void 237 map_pix_to_unit(const OfxPointI& p_pix, OfxPointD* p_unit) const 238 { 239 // We construct (x_s,y_s) in a way, so that the image area is mapped to the unit interval [0,1]^2, 240 // which is required by our 3DE4 lens distortion plugin class. Nuke's coordinates are pixel based, 241 // (0,0) is the left lower corner of the left lower pixel, while (1,1) is the right upper corner 242 // of that pixel. The center of any pixel (ix,iy) is (ix+0.5,iy+0.5), so we add 0.5 here. 243 double x_s = (0.5 + p_pix.x) / _w; 244 double y_s = (0.5 + p_pix.y) / _h; 245 p_unit->x = map_in_fov_x(x_s); 246 p_unit->y = map_in_fov_y(y_s); 247 } 248 249 void 250 map_unit_to_pix(const OfxPointD& p_unit, OfxPointD* p_pix) const 251 { 252 // The result already contains the (half,half) shift. Reformulate in Nuke's coordinates. Weave "out" 3DE4's field of view. 253 p_pix->x = map_out_fov_x(p_unit.x) * _w; 254 p_pix->y = map_out_fov_y(p_unit.y) * _h; 255 } 256 #endif 257 258 void map_pix_to_unit(const OfxPointD & p_pix,OfxPointD * p_unit)259 map_pix_to_unit(const OfxPointD& p_pix, OfxPointD* p_unit) const 260 { 261 double x_s = p_pix.x / _w; 262 double y_s = p_pix.y / _h; 263 p_unit->x = map_in_fov_x(x_s); 264 p_unit->y = map_in_fov_y(y_s); 265 } 266 267 void map_unit_to_pix(const OfxPointD & p_unit,OfxPointD * p_pix)268 map_unit_to_pix(const OfxPointD& p_unit, OfxPointD* p_pix) const 269 { 270 // The result already contains the (half,half) shift. Reformulate in Nuke's coordinates. Weave "out" 3DE4's field of view. 271 p_pix->x = map_out_fov_x(p_unit.x) * _w; 272 p_pix->y = map_out_fov_y(p_unit.y) * _h; 273 } 274 275 // Map x-coordinate from unit cordinates to fov coordinates. 276 double map_in_fov_x(double x_unit)277 map_in_fov_x(double x_unit) const 278 { 279 return (x_unit - _xa_fov_unit) / _xd_fov_unit; 280 } 281 282 // Map y-coordinate from unit cordinates to fov coordinates. 283 double map_in_fov_y(double y_unit)284 map_in_fov_y(double y_unit) const 285 { 286 return (y_unit - _ya_fov_unit) / _yd_fov_unit; 287 } 288 289 // Map x-coordinate from fov cordinates to unit coordinates. 290 double map_out_fov_x(double x_fov)291 map_out_fov_x(double x_fov) const 292 { 293 return x_fov * _xd_fov_unit + _xa_fov_unit; 294 } 295 296 // Map y-coordinate from fov cordinates to unit coordinates. 297 double map_out_fov_y(double y_fov)298 map_out_fov_y(double y_fov) const 299 { 300 return y_fov * _yd_fov_unit + _ya_fov_unit; 301 } 302 303 protected: 304 305 OfxRectD _format; 306 OfxPointD _rs; 307 double _w; 308 double _h; 309 double _xa_fov_unit; 310 double _ya_fov_unit; 311 double _xb_fov_unit; 312 double _yb_fov_unit; 313 double _xd_fov_unit; 314 double _yd_fov_unit; 315 double _fl_cm; 316 double _fd_cm; 317 double _w_fb_cm; 318 double _h_fb_cm; 319 double _x_lco_cm; 320 double _y_lco_cm; 321 double _pa; 322 double _r_fb_cm; 323 }; 324 325 /// this class handles the Degree-2 anamorphic and degree-4 radial mixed model 326 class DistortionModel3DEClassic 327 : public DistortionModel3DEBase 328 { 329 public: 330 DistortionModel3DEClassic(const OfxRectD& format, 331 const OfxPointD& renderScale, 332 double xa_fov_unit, 333 double ya_fov_unit, 334 double xb_fov_unit, 335 double yb_fov_unit, 336 double fl_cm, 337 double fd_cm, 338 double w_fb_cm, 339 double h_fb_cm, 340 double x_lco_cm, 341 double y_lco_cm, 342 double pa, 343 double ld, 344 double sq, 345 double cx, 346 double cy, 347 double qu); 348 ~DistortionModel3DEClassic()349 virtual ~DistortionModel3DEClassic() {}; 350 351 private: 352 // Remove distortion. p is a point in diagonally normalized coordinates. 353 void undistort_dn(double xd, double yd, double* xu, double *yu) const OVERRIDE FINAL; 354 355 private: 356 double _ld; 357 double _sq; 358 double _cx; 359 double _cy; 360 double _qu; 361 double _cxx; 362 double _cxy; 363 double _cyx; 364 double _cyy; 365 double _cxxx; 366 double _cxxy; 367 double _cxyy; 368 double _cyxx; 369 double _cyyx; 370 double _cyyy; 371 }; 372 373 // Degree-6 anamorphic model 374 class DistortionModel3DEAnamorphic6 375 : public DistortionModel3DEBase 376 { 377 public: 378 DistortionModel3DEAnamorphic6(const OfxRectD& format, 379 const OfxPointD& renderScale, 380 double xa_fov_unit, 381 double ya_fov_unit, 382 double xb_fov_unit, 383 double yb_fov_unit, 384 double fl_cm, 385 double fd_cm, 386 double w_fb_cm, 387 double h_fb_cm, 388 double x_lco_cm, 389 double y_lco_cm, 390 double pa, 391 double cx02, 392 double cy02, 393 double cx22, 394 double cy22, 395 double cx04, 396 double cy04, 397 double cx24, 398 double cy24, 399 double cx44, 400 double cy44, 401 double cx06, 402 double cy06, 403 double cx26, 404 double cy26, 405 double cx46, 406 double cy46, 407 double cx66, 408 double cy66); 409 ~DistortionModel3DEAnamorphic6()410 virtual ~DistortionModel3DEAnamorphic6() {}; 411 412 private: 413 // Remove distortion. p is a point in diagonally normalized coordinates. 414 void undistort_dn(double xd, double yd, double* xu, double *yu) const OVERRIDE FINAL; 415 416 private: 417 double _cx_for_x2, _cx_for_y2, _cx_for_x4, _cx_for_x2_y2, _cx_for_y4, _cx_for_x6, _cx_for_x4_y2, _cx_for_x2_y4, _cx_for_y6; 418 double _cy_for_x2, _cy_for_y2, _cy_for_x4, _cy_for_x2_y2, _cy_for_y4, _cy_for_x6, _cy_for_x4_y2, _cy_for_x2_y4, _cy_for_y6; 419 }; 420 421 // radial lens distortion model with equisolid-angle fisheye projection 422 class DistortionModel3DEFishEye8 423 : public DistortionModel3DEBase 424 { 425 public: 426 DistortionModel3DEFishEye8(const OfxRectD& format, 427 const OfxPointD& renderScale, 428 double xa_fov_unit, 429 double ya_fov_unit, 430 double xb_fov_unit, 431 double yb_fov_unit, 432 double fl_cm, 433 double fd_cm, 434 double w_fb_cm, 435 double h_fb_cm, 436 double x_lco_cm, 437 double y_lco_cm, 438 double pa, 439 double c2, 440 double c4, 441 double c6, 442 double c8); 443 ~DistortionModel3DEFishEye8()444 virtual ~DistortionModel3DEFishEye8() {}; 445 446 private: 447 // Remove distortion. p is a point in diagonally normalized coordinates. 448 void undistort_dn(double xd, double yd, double* xu, double *yu) const OVERRIDE FINAL; 449 450 void 451 esa2plain(double x_esa_dn, double y_esa_dn, double *x_plain_dn, double *y_plain_dn) const; 452 453 private: 454 double _c2; 455 double _c4; 456 double _c6; 457 double _c8; 458 }; 459 460 /// this class handles the radial distortion with decentering and optional compensation for beam-splitter artefacts model 461 class DistortionModel3DEStandard 462 : public DistortionModel3DEBase 463 { 464 public: 465 DistortionModel3DEStandard(const OfxRectD& format, 466 const OfxPointD& renderScale, 467 double xa_fov_unit, 468 double ya_fov_unit, 469 double xb_fov_unit, 470 double yb_fov_unit, 471 double fl_cm, 472 double fd_cm, 473 double w_fb_cm, 474 double h_fb_cm, 475 double x_lco_cm, 476 double y_lco_cm, 477 double pa, 478 double c2, 479 double u1, 480 double v1, 481 double c4, 482 double u3, 483 double v3, 484 double phi, 485 double b); 486 ~DistortionModel3DEStandard()487 virtual ~DistortionModel3DEStandard() {}; 488 489 private: 490 // Remove distortion. p is a point in diagonally normalized coordinates. 491 void undistort_dn(double xd, double yd, double* xu, double *yu) const OVERRIDE FINAL; 492 493 private: 494 double _c2; 495 double _u1; 496 double _v1; 497 double _c4; 498 double _u3; 499 double _v3; 500 double _mxx; 501 double _mxy; 502 double _myy; 503 }; 504 505 // Degree-4 anamorphic model with anamorphic lens rotation 506 class DistortionModel3DEAnamorphic4 507 : public DistortionModel3DEBase 508 { 509 public: 510 DistortionModel3DEAnamorphic4(const OfxRectD& format, 511 const OfxPointD& renderScale, 512 double xa_fov_unit, 513 double ya_fov_unit, 514 double xb_fov_unit, 515 double yb_fov_unit, 516 double fl_cm, 517 double fd_cm, 518 double w_fb_cm, 519 double h_fb_cm, 520 double x_lco_cm, 521 double y_lco_cm, 522 double pa, 523 double cx02, 524 double cy02, 525 double cx22, 526 double cy22, 527 double cx04, 528 double cy04, 529 double cx24, 530 double cy24, 531 double cx44, 532 double cy44, 533 double phi, 534 double sqx, 535 double sqy); 536 ~DistortionModel3DEAnamorphic4()537 virtual ~DistortionModel3DEAnamorphic4() {}; 538 539 private: 540 // Remove distortion. p is a point in diagonally normalized coordinates. 541 void undistort_dn(double xd, double yd, double* xu, double *yu) const OVERRIDE FINAL; 542 543 private: 544 double _cx_for_x2, _cx_for_y2, _cx_for_x4, _cx_for_x2_y2, _cx_for_y4; 545 double _cy_for_x2, _cy_for_y2, _cy_for_x4, _cy_for_x2_y2, _cy_for_y4; 546 double _cosphi; 547 double _sinphi; 548 double _sqx; 549 double _sqy; 550 }; 551 552 class DistortionModelPanoTools 553 : public DistortionModelDistort 554 { 555 public: 556 DistortionModelPanoTools(const OfxRectD& format, 557 const OfxPointD& renderScale, 558 double par, 559 double a, 560 double b, 561 double c, 562 double d, 563 double e, 564 double g, 565 double t); 566 ~DistortionModelPanoTools()567 virtual ~DistortionModelPanoTools() {}; 568 569 private: 570 // (xd,yd) = 0,0 at the bottom left of the bottomleft pixel 571 // function used to distort a point or undistort an image 572 virtual void distort(double xu, double yu, double* xd, double *yd) const OVERRIDE FINAL; 573 574 OfxPointD _rs; 575 double _par; 576 double _f; 577 double _xSrcCenter; 578 double _ySrcCenter; 579 double _a; 580 double _b; 581 double _c; 582 double _d; 583 double _e; 584 double _g; 585 double _t; 586 }; 587 588 OFXS_NAMESPACE_OFX_EXIT 589 590 #endif // DistortionModels_h 591