Home | History | Annotate | Download | only in source
      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 
     42 class 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 
    226 class 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 
    349 class 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 
    454 class 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 
    490 class 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 
    527 class 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 
    575 class 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