1/*****************************************************************************/
2// Copyright 2008 Adobe Systems Incorporated
3// All Rights Reserved.
4//
5// NOTICE: Adobe permits you to use, modify, and distribute this file in
6// accordance with the terms of the Adobe license agreement accompanying it.
7/*****************************************************************************/
8
9/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_lens_correction.h#2 $ */
10/* $DateTime: 2012/08/02 06:09:06 $ */
11/* $Change: 841096 $ */
12/* $Author: erichan $ */
13
14/** \file
15 * Opcodes to fix lens aberrations such as geometric distortion, lateral chromatic
16 * aberration, and vignetting (peripheral illumination falloff).
17 */
18
19/*****************************************************************************/
20
21#ifndef __dng_lens_correction__
22#define __dng_lens_correction__
23
24/*****************************************************************************/
25
26#include "dng_1d_function.h"
27#include "dng_matrix.h"
28#include "dng_memory.h"
29#include "dng_opcodes.h"
30#include "dng_pixel_buffer.h"
31#include "dng_point.h"
32#include "dng_resample.h"
33#include "dng_sdk_limits.h"
34
35#include <vector>
36
37/*****************************************************************************/
38
39/// \brief Abstract base class holding common warp opcode parameters (e.g.,
40/// number of planes, optical center) and common warp routines.
41
42class dng_warp_params
43 {
44
45 public:
46
47 // Number of planes to be warped. Must be either 1 or equal to the
48 // number of planes of the image to be processed. If set to 1, then a
49 // single set of warp parameters applies to all planes of the image.
50 // fPlanes must be at least 1 and no greater than kMaxColorPlanes (see
51 // dng_sdk_limits.h).
52
53 uint32 fPlanes;
54
55 // The optical center of the lens in normalized [0,1] coordinates with
56 // respect to the image's active area. For example, a value of (0.5,
57 // 0.5) indicates that the optical center of the lens is at the center
58 // of the image's active area. A normalized radius of 1.0 corresponds to
59 // the distance from fCenter to the farthest corner of the image's
60 // active area. Each component of fCenter must lie in the range [0,1].
61
62 dng_point_real64 fCenter;
63
64 public:
65
66 /// Create empty (invalid) warp parameters.
67
68 dng_warp_params ();
69
70 /// Create warp parameters with specified number of planes and image
71 /// center.
72 ///
73 /// \param planes The number of planes of parameters specified: It must
74 /// be either 1 or equal to the number of planes of the image to be
75 /// processed.
76 ///
77 /// \param fCenter The image center in relative coordinates.
78
79 dng_warp_params (uint32 planes,
80 const dng_point_real64 &fCenter);
81
82 virtual ~dng_warp_params ();
83
84 /// Is the entire correction a NOP for all planes?
85
86 virtual bool IsNOPAll () const;
87
88 /// Is the entire correction a NOP for the specified plane?
89
90 virtual bool IsNOP (uint32 plane) const;
91
92 /// Is the radial correction a NOP for all planes?
93
94 virtual bool IsRadNOPAll () const;
95
96 /// Is the radial correction a NOP for the specified plane?
97
98 virtual bool IsRadNOP (uint32 plane) const;
99
100 /// Is the tangential correction a NOP for all planes?
101
102 virtual bool IsTanNOPAll () const;
103
104 /// Is the tangential correction a NOP for the specified plane?
105
106 virtual bool IsTanNOP (uint32 plane) const;
107
108 /// Do these warp params appear valid?
109
110 virtual bool IsValid () const;
111
112 /// Are these warp params valid for the specified negative?
113
114 virtual bool IsValidForNegative (const dng_negative &negative) const;
115
116 /// Propagate warp parameters from first plane to all other planes.
117
118 virtual void PropagateToAllPlanes (uint32 totalPlanes) = 0;
119
120 /// Evaluate the 1D radial warp function for the specified plane.
121 /// Parameter r is the destination (i.e., corrected) normalized radius,
122 /// i.e., the normalized Euclidean distance between a corrected pixel
123 /// position and the optical center in the image. r lies in the range
124 /// [0,1]. The returned result is non-negative.
125
126 virtual real64 Evaluate (uint32 plane,
127 real64 r) const = 0;
128
129 /// Compute and return the inverse of Evaluate () above. The base
130 /// implementation uses Newton's method to perform the inversion.
131 /// Parameter r is the source (i.e., uncorrected) normalized radius,
132 /// i.e., normalized Euclidean distance between a corrected pixel
133 /// position and the optical center in the image. Both r and the
134 /// computed result are non-negative.
135
136 virtual real64 EvaluateInverse (uint32 plane,
137 real64 r) const;
138
139 /// Evaluate the 1D radial warp ratio function for the specified plane.
140 /// Parameter r2 is the square of the destination (i.e., corrected)
141 /// normalized radius, i.e., the square of the normalized Euclidean
142 /// distance between a corrected pixel position and the optical center
143 /// in the image. r2 must lie in the range [0,1]. Note that this is
144 /// different than the Evaluate () function, above, in that the argument
145 /// to EvaluateRatio () is the square of the radius, not the radius
146 /// itself. The returned result is non-negative. Mathematically,
147 /// EvaluateRatio (r * r) is the same as Evaluate (r) / r.
148
149 virtual real64 EvaluateRatio (uint32 plane,
150 real64 r2) const = 0;
151
152 /// Evaluate the 2D tangential warp for the specified plane. Parameter
153 /// r2 is the square of the destination (i.e., corrected) normalized
154 /// radius, i.e., the square of the normalized Euclidean distance
155 /// between a corrected pixel position P and the optical center in the
156 /// image. r2 must lie in the range [0,1]. diff contains the vertical
157 /// and horizontal Euclidean distances (in pixels) between P and the
158 /// optical center. diff2 contains the squares of the vertical and
159 /// horizontal Euclidean distances (in pixels) between P and the optical
160 /// center. The returned result is the tangential warp offset, measured
161 /// in pixels.
162
163 virtual dng_point_real64 EvaluateTangential (uint32 plane,
164 real64 r2,
165 const dng_point_real64 &diff,
166 const dng_point_real64 &diff2) const = 0;
167
168 /// Evaluate the 2D tangential warp for the specified plane. diff
169 /// contains the vertical and horizontal Euclidean distances (in pixels)
170 /// between the destination (i.e., corrected) pixel position and the
171 /// optical center in the image. The returned result is the tangential
172 /// warp offset, measured in pixels.
173
174 dng_point_real64 EvaluateTangential2 (uint32 plane,
175 const dng_point_real64 &diff) const;
176
177 /// Evaluate the 2D tangential warp for the specified plane. Parameter
178 /// r2 is the square of the destination (i.e., corrected) normalized
179 /// radius, i.e., the square of the normalized Euclidean distance
180 /// between a corrected pixel position P and the optical center in the
181 /// image. r2 must lie in the range [0,1]. diff contains the vertical
182 /// and horizontal Euclidean distances (in pixels) between P and the
183 /// optical center. The returned result is the tangential warp offset,
184 /// measured in pixels.
185
186 dng_point_real64 EvaluateTangential3 (uint32 plane,
187 real64 r2,
188 const dng_point_real64 &diff) const;
189
190 /// Compute and return the maximum warped radius gap. Let D be a
191 /// rectangle in a destination (corrected) image. Let rDstFar and
192 /// rDstNear be the farthest and nearest points to the image center,
193 /// respectively. Then the specified parameter maxDstGap is the
194 /// Euclidean distance between rDstFar and rDstNear. Warp D through this
195 /// warp function to a closed and bounded (generally not rectangular)
196 /// region S. Let rSrcfar and rSrcNear be the farthest and nearest
197 /// points to the image center, respectively. This routine returns a
198 /// value that is at least (rSrcFar - rSrcNear).
199
200 virtual real64 MaxSrcRadiusGap (real64 maxDstGap) const = 0;
201
202 /// Compute and return the maximum warped tangential gap. minDst is the
203 /// top-left pixel of the image in normalized pixel coordinates. maxDst
204 /// is the bottom-right pixel of the image in normalized pixel
205 /// coordinates. MaxSrcTanGap () computes the maximum absolute shift in
206 /// normalized pixels in the horizontal and vertical directions that can
207 /// occur as a result of the tangential warp.
208
209 virtual dng_point_real64 MaxSrcTanGap (dng_point_real64 minDst,
210 dng_point_real64 maxDst) const = 0;
211
212 /// Debug parameters.
213
214 virtual void Dump () const;
215
216 };
217
218/*****************************************************************************/
219
220/// \brief Warp parameters for pinhole perspective rectilinear (not fisheye)
221/// camera model. Supports radial and tangential (decentering) distortion
222/// correction parameters.
223///
224/// Note the restrictions described below.
225
226class dng_warp_params_rectilinear: public dng_warp_params
227 {
228
229 public:
230
231 // Radial and tangential polynomial coefficients. These define a warp
232 // from corrected pixel coordinates (xDst, yDst) to uncorrected pixel
233 // coordinates (xSrc, ySrc) for each plane P as follows:
234 //
235 // Let kr0 = fRadParams [P][0]
236 // kr1 = fRadParams [P][1]
237 // kr2 = fRadParams [P][2]
238 // kr3 = fRadParams [P][3]
239 //
240 // kt0 = fTanParams [P][0]
241 // kt1 = fTanParams [P][1]
242 //
243 // Let (xCenter, yCenter) be the optical image center (see fCenter,
244 // below) expressed in pixel coordinates. Let maxDist be the Euclidean
245 // distance (in pixels) from (xCenter, yCenter) to the farthest image
246 // corner.
247 //
248 // First, compute the normalized distance of the corrected pixel
249 // position (xDst, yDst) from the image center:
250 //
251 // dx = (xDst - xCenter) / maxDist
252 // dy = (yDst - yCenter) / maxDist
253 //
254 // r^2 = dx^2 + dy^2
255 //
256 // Compute the radial correction term:
257 //
258 // ratio = kr0 + (kr1 * r^2) + (kr2 * r^4) + (kr3 * r^6)
259 //
260 // dxRad = dx * ratio
261 // dyRad = dy * ratio
262 //
263 // Compute the tangential correction term:
264 //
265 // dxTan = (2 * kt0 * dx * dy) + kt1 * (r^2 + 2 * dx^2)
266 // dyTan = (2 * kt1 * dx * dy) + kt0 * (r^2 + 2 * dy^2)
267 //
268 // Compute the uncorrected pixel position (xSrc, ySrc):
269 //
270 // xSrc = xCenter + (dxRad + dxTan) * maxDist
271 // ySrc = yCenter + (dyRad + dyTan) * maxDist
272 //
273 // Mathematical definitions and restrictions:
274 //
275 // Let { xSrc, ySrc } = f (xDst, yDst) be the warp function defined
276 // above.
277 //
278 // Let xSrc = fx (xDst, yDst) be the x-component of the warp function.
279 // Let ySrc = fy (xDst, yDst) be the y-component of the warp function.
280 //
281 // f (x, y) must be an invertible function.
282 //
283 // fx (x, y) must be an increasing function of x.
284 // fy (x, y) must be an increasing function of x.
285 //
286 // The parameters kr0, kr1, kr2, and kr3 must define an increasing
287 // radial warp function. Specifically, let w (r) be the radial warp
288 // function:
289 //
290 // w (r) = (kr0 * r) + (kr1 * r^3) + (kr2 * r^5) + (kr3 * r^7).
291 //
292 // w (r) must be an increasing function.
293
294 dng_vector fRadParams [kMaxColorPlanes];
295 dng_vector fTanParams [kMaxColorPlanes];
296
297 public:
298
299 /// Create empty (invalid) rectilinear warp parameters.
300
301 dng_warp_params_rectilinear ();
302
303 /// Create rectilinear warp parameters with the specified number of
304 /// planes, radial component terms, tangential component terms, and
305 /// image center in relative coordinates.
306
307 dng_warp_params_rectilinear (uint32 planes,
308 const dng_vector radParams [],
309 const dng_vector tanParams [],
310 const dng_point_real64 &fCenter);
311
312 virtual ~dng_warp_params_rectilinear ();
313
314 // Overridden methods.
315
316 virtual bool IsRadNOP (uint32 plane) const;
317
318 virtual bool IsTanNOP (uint32 plane) const;
319
320 virtual bool IsValid () const;
321
322 virtual void PropagateToAllPlanes (uint32 totalPlanes);
323
324 virtual real64 Evaluate (uint32 plane,
325 real64 r) const;
326
327 virtual real64 EvaluateRatio (uint32 plane,
328 real64 r2) const;
329
330 virtual dng_point_real64 EvaluateTangential (uint32 plane,
331 real64 r2,
332 const dng_point_real64 &diff,
333 const dng_point_real64 &diff2) const;
334
335 virtual real64 MaxSrcRadiusGap (real64 maxDstGap) const;
336
337 virtual dng_point_real64 MaxSrcTanGap (dng_point_real64 minDst,
338 dng_point_real64 maxDst) const;
339
340 virtual void Dump () const;
341
342 };
343
344/*****************************************************************************/
345
346/// \brief Warp parameters for fisheye camera model (radial component only).
347/// Note the restrictions described below.
348
349class dng_warp_params_fisheye: public dng_warp_params
350 {
351
352 public:
353
354 // Radial warp coefficients. These define a warp from corrected pixel
355 // coordinates (xDst, yDst) to uncorrected pixel coordinates (xSrc,
356 // ySrc) for each plane P as follows:
357 //
358 // Let kr0 = fRadParams [P][0]
359 // kr1 = fRadParams [P][1]
360 // kr2 = fRadParams [P][2]
361 // kr3 = fRadParams [P][3]
362 //
363 // Let (xCenter, yCenter) be the optical image center (see fCenter,
364 // below) expressed in pixel coordinates. Let maxDist be the Euclidean
365 // distance (in pixels) from (xCenter, yCenter) to the farthest image
366 // corner.
367 //
368 // First, compute the normalized distance of the corrected pixel
369 // position (xDst, yDst) from the image center:
370 //
371 // dx = (xDst - xCenter) / maxDist
372 // dy = (yDst - yCenter) / maxDist
373 //
374 // r = sqrt (dx^2 + dy^2)
375 //
376 // Compute the radial correction term:
377 //
378 // t = atan (r)
379 //
380 // rWarp = (kr0 * t) + (kr1 * t^3) + (kr2 * t^5) + (kr3 * t^7)
381 //
382 // ratio = rWarp / r
383 //
384 // dxRad = dx * ratio
385 // dyRad = dy * ratio
386 //
387 // Compute the uncorrected pixel position (xSrc, ySrc):
388 //
389 // xSrc = xCenter + (dxRad * maxDist)
390 // ySrc = yCenter + (dyRad * maxDist)
391 //
392 // The parameters kr0, kr1, kr2, and kr3 must define an increasing
393 // radial warp function. Specifically, let w (r) be the radial warp
394 // function:
395 //
396 // t = atan (r)
397 //
398 // w (r) = (kr0 * t) + (kr1 * t^3) + (kr2 * t^5) + (kr3 * t^7).
399 //
400 // w (r) must be an increasing function.
401
402 dng_vector fRadParams [kMaxColorPlanes];
403
404 public:
405
406 /// Create empty (invalid) fisheye warp parameters.
407
408 dng_warp_params_fisheye ();
409
410 /// Create rectilinear warp parameters with the specified number of
411 /// planes, radial component terms, and image center in relative
412 /// coordinates.
413
414 dng_warp_params_fisheye (uint32 planes,
415 const dng_vector radParams [],
416 const dng_point_real64 &fCenter);
417
418 virtual ~dng_warp_params_fisheye ();
419
420 // Overridden methods.
421
422 virtual bool IsRadNOP (uint32 plane) const;
423
424 virtual bool IsTanNOP (uint32 plane) const;
425
426 virtual bool IsValid () const;
427
428 virtual void PropagateToAllPlanes (uint32 totalPlanes);
429
430 virtual real64 Evaluate (uint32 plane,
431 real64 r) const;
432
433 virtual real64 EvaluateRatio (uint32 plane,
434 real64 r2) const;
435
436 virtual dng_point_real64 EvaluateTangential (uint32 plane,
437 real64 r2,
438 const dng_point_real64 &diff,
439 const dng_point_real64 &diff2) const;
440
441 virtual real64 MaxSrcRadiusGap (real64 maxDstGap) const;
442
443 virtual dng_point_real64 MaxSrcTanGap (dng_point_real64 minDst,
444 dng_point_real64 maxDst) const;
445
446 virtual void Dump () const;
447
448 };
449
450/*****************************************************************************/
451
452/// \brief Warp opcode for pinhole perspective (rectilinear) camera model.
453
454class dng_opcode_WarpRectilinear: public dng_opcode
455 {
456
457 protected:
458
459 dng_warp_params_rectilinear fWarpParams;
460
461 public:
462
463 dng_opcode_WarpRectilinear (const dng_warp_params_rectilinear &params,
464 uint32 flags);
465
466 explicit dng_opcode_WarpRectilinear (dng_stream &stream);
467
468 // Overridden methods.
469
470 virtual bool IsNOP () const;
471
472 virtual bool IsValidForNegative (const dng_negative &negative) const;
473
474 virtual void PutData (dng_stream &stream) const;
475
476 virtual void Apply (dng_host &host,
477 dng_negative &negative,
478 AutoPtr<dng_image> &image);
479
480 protected:
481
482 static uint32 ParamBytes (uint32 planes);
483
484 };
485
486/*****************************************************************************/
487
488/// \brief Warp opcode for fisheye camera model.
489
490class dng_opcode_WarpFisheye: public dng_opcode
491 {
492
493 protected:
494
495 dng_warp_params_fisheye fWarpParams;
496
497 public:
498
499 dng_opcode_WarpFisheye (const dng_warp_params_fisheye &params,
500 uint32 flags);
501
502 explicit dng_opcode_WarpFisheye (dng_stream &stream);
503
504 // Overridden methods.
505
506 virtual bool IsNOP () const;
507
508 virtual bool IsValidForNegative (const dng_negative &negative) const;
509
510 virtual void PutData (dng_stream &stream) const;
511
512 virtual void Apply (dng_host &host,
513 dng_negative &negative,
514 AutoPtr<dng_image> &image);
515
516 protected:
517
518 static uint32 ParamBytes (uint32 planes);
519
520 };
521
522/*****************************************************************************/
523
524/// \brief Radially-symmetric vignette (peripheral illuminational falloff)
525/// correction parameters.
526
527class dng_vignette_radial_params
528 {
529
530 public:
531
532 static const uint32 kNumTerms = 5;
533
534 public:
535
536 // Let v be an uncorrected pixel value of a pixel p in linear space.
537 //
538 // Let r be the Euclidean distance between p and the optical center.
539 //
540 // Compute corrected pixel value v' = v * g, where g is the gain.
541 //
542 // Let k0 = fParams [0]
543 // Let k1 = fParams [1]
544 // Let k2 = fParams [2]
545 // Let k3 = fParams [3]
546 // Let k4 = fParams [4]
547 //
548 // Gain g = 1 + (k0 * r^2) + (k1 * r^4) + (k2 * r^6) + (k3 * r^8) + (k4 * r^10)
549
550 dng_std_vector<real64> fParams;
551
552 dng_point_real64 fCenter;
553
554 public:
555
556 dng_vignette_radial_params ();
557
558 dng_vignette_radial_params (const dng_std_vector<real64> &params,
559 const dng_point_real64 &center);
560
561 bool IsNOP () const;
562
563 bool IsValid () const;
564
565 // For debugging.
566
567 void Dump () const;
568
569 };
570
571/*****************************************************************************/
572
573/// \brief Radially-symmetric lens vignette correction opcode.
574
575class dng_opcode_FixVignetteRadial: public dng_inplace_opcode
576 {
577
578 protected:
579
580 dng_vignette_radial_params fParams;
581
582 uint32 fImagePlanes;
583
584 int64 fSrcOriginH;
585 int64 fSrcOriginV;
586
587 int64 fSrcStepH;
588 int64 fSrcStepV;
589
590 uint32 fTableInputBits;
591 uint32 fTableOutputBits;
592
593 AutoPtr<dng_memory_block> fGainTable;
594
595 AutoPtr<dng_memory_block> fMaskBuffers [kMaxMPThreads];
596
597 public:
598
599 dng_opcode_FixVignetteRadial (const dng_vignette_radial_params &params,
600 uint32 flags);
601
602 explicit dng_opcode_FixVignetteRadial (dng_stream &stream);
603
604 virtual bool IsNOP () const;
605
606 virtual bool IsValidForNegative (const dng_negative &) const;
607
608 virtual void PutData (dng_stream &stream) const;
609
610 virtual uint32 BufferPixelType (uint32 /* imagePixelType */)
611 {
612 return ttFloat;
613 }
614
615 virtual void Prepare (dng_negative &negative,
616 uint32 threadCount,
617 const dng_point &tileSize,
618 const dng_rect &imageBounds,
619 uint32 imagePlanes,
620 uint32 bufferPixelType,
621 dng_memory_allocator &allocator);
622
623 virtual void ProcessArea (dng_negative &negative,
624 uint32 threadIndex,
625 dng_pixel_buffer &buffer,
626 const dng_rect &dstArea,
627 const dng_rect &imageBounds);
628
629 protected:
630
631 static uint32 ParamBytes ();
632
633 };
634
635/*****************************************************************************/
636
637#endif
638
639/*****************************************************************************/
640