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