/*****************************************************************************/
// Copyright 2008 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in
// accordance with the terms of the Adobe license agreement accompanying it.
/*****************************************************************************/
/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_lens_correction.h#2 $ */
/* $DateTime: 2012/08/02 06:09:06 $ */
/* $Change: 841096 $ */
/* $Author: erichan $ */
/** \file
* Opcodes to fix lens aberrations such as geometric distortion, lateral chromatic
* aberration, and vignetting (peripheral illumination falloff).
*/
/*****************************************************************************/
#ifndef __dng_lens_correction__
#define __dng_lens_correction__
/*****************************************************************************/
#include "dng_1d_function.h"
#include "dng_matrix.h"
#include "dng_memory.h"
#include "dng_opcodes.h"
#include "dng_pixel_buffer.h"
#include "dng_point.h"
#include "dng_resample.h"
#include "dng_sdk_limits.h"
#include <vector>
/*****************************************************************************/
/// \brief Abstract base class holding common warp opcode parameters (e.g.,
/// number of planes, optical center) and common warp routines.
class dng_warp_params
{
public:
// Number of planes to be warped. Must be either 1 or equal to the
// number of planes of the image to be processed. If set to 1, then a
// single set of warp parameters applies to all planes of the image.
// fPlanes must be at least 1 and no greater than kMaxColorPlanes (see
// dng_sdk_limits.h).
uint32 fPlanes;
// The optical center of the lens in normalized [0,1] coordinates with
// respect to the image's active area. For example, a value of (0.5,
// 0.5) indicates that the optical center of the lens is at the center
// of the image's active area. A normalized radius of 1.0 corresponds to
// the distance from fCenter to the farthest corner of the image's
// active area. Each component of fCenter must lie in the range [0,1].
dng_point_real64 fCenter;
public:
/// Create empty (invalid) warp parameters.
dng_warp_params ();
/// Create warp parameters with specified number of planes and image
/// center.
///
/// \param planes The number of planes of parameters specified: It must
/// be either 1 or equal to the number of planes of the image to be
/// processed.
///
/// \param fCenter The image center in relative coordinates.
dng_warp_params (uint32 planes,
const dng_point_real64 &fCenter);
virtual ~dng_warp_params ();
/// Is the entire correction a NOP for all planes?
virtual bool IsNOPAll () const;
/// Is the entire correction a NOP for the specified plane?
virtual bool IsNOP (uint32 plane) const;
/// Is the radial correction a NOP for all planes?
virtual bool IsRadNOPAll () const;
/// Is the radial correction a NOP for the specified plane?
virtual bool IsRadNOP (uint32 plane) const;
/// Is the tangential correction a NOP for all planes?
virtual bool IsTanNOPAll () const;
/// Is the tangential correction a NOP for the specified plane?
virtual bool IsTanNOP (uint32 plane) const;
/// Do these warp params appear valid?
virtual bool IsValid () const;
/// Are these warp params valid for the specified negative?
virtual bool IsValidForNegative (const dng_negative &negative) const;
/// Propagate warp parameters from first plane to all other planes.
virtual void PropagateToAllPlanes (uint32 totalPlanes) = 0;
/// Evaluate the 1D radial warp function for the specified plane.
/// Parameter r is the destination (i.e., corrected) normalized radius,
/// i.e., the normalized Euclidean distance between a corrected pixel
/// position and the optical center in the image. r lies in the range
/// [0,1]. The returned result is non-negative.
virtual real64 Evaluate (uint32 plane,
real64 r) const = 0;
/// Compute and return the inverse of Evaluate () above. The base
/// implementation uses Newton's method to perform the inversion.
/// Parameter r is the source (i.e., uncorrected) normalized radius,
/// i.e., normalized Euclidean distance between a corrected pixel
/// position and the optical center in the image. Both r and the
/// computed result are non-negative.
virtual real64 EvaluateInverse (uint32 plane,
real64 r) const;
/// Evaluate the 1D radial warp ratio function for the specified plane.
/// Parameter r2 is the square of the destination (i.e., corrected)
/// normalized radius, i.e., the square of the normalized Euclidean
/// distance between a corrected pixel position and the optical center
/// in the image. r2 must lie in the range [0,1]. Note that this is
/// different than the Evaluate () function, above, in that the argument
/// to EvaluateRatio () is the square of the radius, not the radius
/// itself. The returned result is non-negative. Mathematically,
/// EvaluateRatio (r * r) is the same as Evaluate (r) / r.
virtual real64 EvaluateRatio (uint32 plane,
real64 r2) const = 0;
/// Evaluate the 2D tangential warp for the specified plane. Parameter
/// r2 is the square of the destination (i.e., corrected) normalized
/// radius, i.e., the square of the normalized Euclidean distance
/// between a corrected pixel position P and the optical center in the
/// image. r2 must lie in the range [0,1]. diff contains the vertical
/// and horizontal Euclidean distances (in pixels) between P and the
/// optical center. diff2 contains the squares of the vertical and
/// horizontal Euclidean distances (in pixels) between P and the optical
/// center. The returned result is the tangential warp offset, measured
/// in pixels.
virtual dng_point_real64 EvaluateTangential (uint32 plane,
real64 r2,
const dng_point_real64 &diff,
const dng_point_real64 &diff2) const = 0;
/// Evaluate the 2D tangential warp for the specified plane. diff
/// contains the vertical and horizontal Euclidean distances (in pixels)
/// between the destination (i.e., corrected) pixel position and the
/// optical center in the image. The returned result is the tangential
/// warp offset, measured in pixels.
dng_point_real64 EvaluateTangential2 (uint32 plane,
const dng_point_real64 &diff) const;
/// Evaluate the 2D tangential warp for the specified plane. Parameter
/// r2 is the square of the destination (i.e., corrected) normalized
/// radius, i.e., the square of the normalized Euclidean distance
/// between a corrected pixel position P and the optical center in the
/// image. r2 must lie in the range [0,1]. diff contains the vertical
/// and horizontal Euclidean distances (in pixels) between P and the
/// optical center. The returned result is the tangential warp offset,
/// measured in pixels.
dng_point_real64 EvaluateTangential3 (uint32 plane,
real64 r2,
const dng_point_real64 &diff) const;
/// Compute and return the maximum warped radius gap. Let D be a
/// rectangle in a destination (corrected) image. Let rDstFar and
/// rDstNear be the farthest and nearest points to the image center,
/// respectively. Then the specified parameter maxDstGap is the
/// Euclidean distance between rDstFar and rDstNear. Warp D through this
/// warp function to a closed and bounded (generally not rectangular)
/// region S. Let rSrcfar and rSrcNear be the farthest and nearest
/// points to the image center, respectively. This routine returns a
/// value that is at least (rSrcFar - rSrcNear).
virtual real64 MaxSrcRadiusGap (real64 maxDstGap) const = 0;
/// Compute and return the maximum warped tangential gap. minDst is the
/// top-left pixel of the image in normalized pixel coordinates. maxDst
/// is the bottom-right pixel of the image in normalized pixel
/// coordinates. MaxSrcTanGap () computes the maximum absolute shift in
/// normalized pixels in the horizontal and vertical directions that can
/// occur as a result of the tangential warp.
virtual dng_point_real64 MaxSrcTanGap (dng_point_real64 minDst,
dng_point_real64 maxDst) const = 0;
/// Debug parameters.
virtual void Dump () const;
};
/*****************************************************************************/
/// \brief Warp parameters for pinhole perspective rectilinear (not fisheye)
/// camera model. Supports radial and tangential (decentering) distortion
/// correction parameters.
///
/// Note the restrictions described below.
class dng_warp_params_rectilinear: public dng_warp_params
{
public:
// Radial and tangential polynomial coefficients. These define a warp
// from corrected pixel coordinates (xDst, yDst) to uncorrected pixel
// coordinates (xSrc, ySrc) for each plane P as follows:
//
// Let kr0 = fRadParams [P][0]
// kr1 = fRadParams [P][1]
// kr2 = fRadParams [P][2]
// kr3 = fRadParams [P][3]
//
// kt0 = fTanParams [P][0]
// kt1 = fTanParams [P][1]
//
// Let (xCenter, yCenter) be the optical image center (see fCenter,
// below) expressed in pixel coordinates. Let maxDist be the Euclidean
// distance (in pixels) from (xCenter, yCenter) to the farthest image
// corner.
//
// First, compute the normalized distance of the corrected pixel
// position (xDst, yDst) from the image center:
//
// dx = (xDst - xCenter) / maxDist
// dy = (yDst - yCenter) / maxDist
//
// r^2 = dx^2 + dy^2
//
// Compute the radial correction term:
//
// ratio = kr0 + (kr1 * r^2) + (kr2 * r^4) + (kr3 * r^6)
//
// dxRad = dx * ratio
// dyRad = dy * ratio
//
// Compute the tangential correction term:
//
// dxTan = (2 * kt0 * dx * dy) + kt1 * (r^2 + 2 * dx^2)
// dyTan = (2 * kt1 * dx * dy) + kt0 * (r^2 + 2 * dy^2)
//
// Compute the uncorrected pixel position (xSrc, ySrc):
//
// xSrc = xCenter + (dxRad + dxTan) * maxDist
// ySrc = yCenter + (dyRad + dyTan) * maxDist
//
// Mathematical definitions and restrictions:
//
// Let { xSrc, ySrc } = f (xDst, yDst) be the warp function defined
// above.
//
// Let xSrc = fx (xDst, yDst) be the x-component of the warp function.
// Let ySrc = fy (xDst, yDst) be the y-component of the warp function.
//
// f (x, y) must be an invertible function.
//
// fx (x, y) must be an increasing function of x.
// fy (x, y) must be an increasing function of x.
//
// The parameters kr0, kr1, kr2, and kr3 must define an increasing
// radial warp function. Specifically, let w (r) be the radial warp
// function:
//
// w (r) = (kr0 * r) + (kr1 * r^3) + (kr2 * r^5) + (kr3 * r^7).
//
// w (r) must be an increasing function.
dng_vector fRadParams [kMaxColorPlanes];
dng_vector fTanParams [kMaxColorPlanes];
public:
/// Create empty (invalid) rectilinear warp parameters.
dng_warp_params_rectilinear ();
/// Create rectilinear warp parameters with the specified number of
/// planes, radial component terms, tangential component terms, and
/// image center in relative coordinates.
dng_warp_params_rectilinear (uint32 planes,
const dng_vector radParams [],
const dng_vector tanParams [],
const dng_point_real64 &fCenter);
virtual ~dng_warp_params_rectilinear ();
// Overridden methods.
virtual bool IsRadNOP (uint32 plane) const;
virtual bool IsTanNOP (uint32 plane) const;
virtual bool IsValid () const;
virtual void PropagateToAllPlanes (uint32 totalPlanes);
virtual real64 Evaluate (uint32 plane,
real64 r) const;
virtual real64 EvaluateRatio (uint32 plane,
real64 r2) const;
virtual dng_point_real64 EvaluateTangential (uint32 plane,
real64 r2,
const dng_point_real64 &diff,
const dng_point_real64 &diff2) const;
virtual real64 MaxSrcRadiusGap (real64 maxDstGap) const;
virtual dng_point_real64 MaxSrcTanGap (dng_point_real64 minDst,
dng_point_real64 maxDst) const;
virtual void Dump () const;
};
/*****************************************************************************/
/// \brief Warp parameters for fisheye camera model (radial component only).
/// Note the restrictions described below.
class dng_warp_params_fisheye: public dng_warp_params
{
public:
// Radial warp coefficients. These define a warp from corrected pixel
// coordinates (xDst, yDst) to uncorrected pixel coordinates (xSrc,
// ySrc) for each plane P as follows:
//
// Let kr0 = fRadParams [P][0]
// kr1 = fRadParams [P][1]
// kr2 = fRadParams [P][2]
// kr3 = fRadParams [P][3]
//
// Let (xCenter, yCenter) be the optical image center (see fCenter,
// below) expressed in pixel coordinates. Let maxDist be the Euclidean
// distance (in pixels) from (xCenter, yCenter) to the farthest image
// corner.
//
// First, compute the normalized distance of the corrected pixel
// position (xDst, yDst) from the image center:
//
// dx = (xDst - xCenter) / maxDist
// dy = (yDst - yCenter) / maxDist
//
// r = sqrt (dx^2 + dy^2)
//
// Compute the radial correction term:
//
// t = atan (r)
//
// rWarp = (kr0 * t) + (kr1 * t^3) + (kr2 * t^5) + (kr3 * t^7)
//
// ratio = rWarp / r
//
// dxRad = dx * ratio
// dyRad = dy * ratio
//
// Compute the uncorrected pixel position (xSrc, ySrc):
//
// xSrc = xCenter + (dxRad * maxDist)
// ySrc = yCenter + (dyRad * maxDist)
//
// The parameters kr0, kr1, kr2, and kr3 must define an increasing
// radial warp function. Specifically, let w (r) be the radial warp
// function:
//
// t = atan (r)
//
// w (r) = (kr0 * t) + (kr1 * t^3) + (kr2 * t^5) + (kr3 * t^7).
//
// w (r) must be an increasing function.
dng_vector fRadParams [kMaxColorPlanes];
public:
/// Create empty (invalid) fisheye warp parameters.
dng_warp_params_fisheye ();
/// Create rectilinear warp parameters with the specified number of
/// planes, radial component terms, and image center in relative
/// coordinates.
dng_warp_params_fisheye (uint32 planes,
const dng_vector radParams [],
const dng_point_real64 &fCenter);
virtual ~dng_warp_params_fisheye ();
// Overridden methods.
virtual bool IsRadNOP (uint32 plane) const;
virtual bool IsTanNOP (uint32 plane) const;
virtual bool IsValid () const;
virtual void PropagateToAllPlanes (uint32 totalPlanes);
virtual real64 Evaluate (uint32 plane,
real64 r) const;
virtual real64 EvaluateRatio (uint32 plane,
real64 r2) const;
virtual dng_point_real64 EvaluateTangential (uint32 plane,
real64 r2,
const dng_point_real64 &diff,
const dng_point_real64 &diff2) const;
virtual real64 MaxSrcRadiusGap (real64 maxDstGap) const;
virtual dng_point_real64 MaxSrcTanGap (dng_point_real64 minDst,
dng_point_real64 maxDst) const;
virtual void Dump () const;
};
/*****************************************************************************/
/// \brief Warp opcode for pinhole perspective (rectilinear) camera model.
class dng_opcode_WarpRectilinear: public dng_opcode
{
protected:
dng_warp_params_rectilinear fWarpParams;
public:
dng_opcode_WarpRectilinear (const dng_warp_params_rectilinear ¶ms,
uint32 flags);
explicit dng_opcode_WarpRectilinear (dng_stream &stream);
// Overridden methods.
virtual bool IsNOP () const;
virtual bool IsValidForNegative (const dng_negative &negative) const;
virtual void PutData (dng_stream &stream) const;
virtual void Apply (dng_host &host,
dng_negative &negative,
AutoPtr<dng_image> &image);
protected:
static uint32 ParamBytes (uint32 planes);
};
/*****************************************************************************/
/// \brief Warp opcode for fisheye camera model.
class dng_opcode_WarpFisheye: public dng_opcode
{
protected:
dng_warp_params_fisheye fWarpParams;
public:
dng_opcode_WarpFisheye (const dng_warp_params_fisheye ¶ms,
uint32 flags);
explicit dng_opcode_WarpFisheye (dng_stream &stream);
// Overridden methods.
virtual bool IsNOP () const;
virtual bool IsValidForNegative (const dng_negative &negative) const;
virtual void PutData (dng_stream &stream) const;
virtual void Apply (dng_host &host,
dng_negative &negative,
AutoPtr<dng_image> &image);
protected:
static uint32 ParamBytes (uint32 planes);
};
/*****************************************************************************/
/// \brief Radially-symmetric vignette (peripheral illuminational falloff)
/// correction parameters.
class dng_vignette_radial_params
{
public:
static const uint32 kNumTerms = 5;
public:
// Let v be an uncorrected pixel value of a pixel p in linear space.
//
// Let r be the Euclidean distance between p and the optical center.
//
// Compute corrected pixel value v' = v * g, where g is the gain.
//
// Let k0 = fParams [0]
// Let k1 = fParams [1]
// Let k2 = fParams [2]
// Let k3 = fParams [3]
// Let k4 = fParams [4]
//
// Gain g = 1 + (k0 * r^2) + (k1 * r^4) + (k2 * r^6) + (k3 * r^8) + (k4 * r^10)
dng_std_vector<real64> fParams;
dng_point_real64 fCenter;
public:
dng_vignette_radial_params ();
dng_vignette_radial_params (const dng_std_vector<real64> ¶ms,
const dng_point_real64 ¢er);
bool IsNOP () const;
bool IsValid () const;
// For debugging.
void Dump () const;
};
/*****************************************************************************/
/// \brief Radially-symmetric lens vignette correction opcode.
class dng_opcode_FixVignetteRadial: public dng_inplace_opcode
{
protected:
dng_vignette_radial_params fParams;
uint32 fImagePlanes;
int64 fSrcOriginH;
int64 fSrcOriginV;
int64 fSrcStepH;
int64 fSrcStepV;
uint32 fTableInputBits;
uint32 fTableOutputBits;
AutoPtr<dng_memory_block> fGainTable;
AutoPtr<dng_memory_block> fMaskBuffers [kMaxMPThreads];
public:
dng_opcode_FixVignetteRadial (const dng_vignette_radial_params ¶ms,
uint32 flags);
explicit dng_opcode_FixVignetteRadial (dng_stream &stream);
virtual bool IsNOP () const;
virtual bool IsValidForNegative (const dng_negative &) const;
virtual void PutData (dng_stream &stream) const;
virtual uint32 BufferPixelType (uint32 /* imagePixelType */)
{
return ttFloat;
}
virtual void Prepare (dng_negative &negative,
uint32 threadCount,
const dng_point &tileSize,
const dng_rect &imageBounds,
uint32 imagePlanes,
uint32 bufferPixelType,
dng_memory_allocator &allocator);
virtual void ProcessArea (dng_negative &negative,
uint32 threadIndex,
dng_pixel_buffer &buffer,
const dng_rect &dstArea,
const dng_rect &imageBounds);
protected:
static uint32 ParamBytes ();
};
/*****************************************************************************/
#endif
/*****************************************************************************/