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 
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