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 ¶ms, 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 ¶ms, 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> ¶ms, 559 const dng_point_real64 ¢er); 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 ¶ms, 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 BufferPixelType(uint32)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